Coverage Report

Created: 2026-06-14 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib/gio/gfileinfo.c
Line
Count
Source
1
/* GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright (C) 2006-2007 Red Hat, Inc.
4
 *
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General
18
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author: Alexander Larsson <alexl@redhat.com>
21
 */
22
23
/**
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
0
G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT)
98
0
99
0
typedef struct {
100
0
  guint32 id;
101
0
  guint32 attribute_id_counter;
102
0
} NSInfo;
103
0
104
0
G_LOCK_DEFINE_STATIC (attribute_hash);
105
0
static int namespace_id_counter = 0;
106
0
static GHashTable *ns_hash = NULL;
107
0
static GHashTable *attribute_hash = NULL;
108
0
static char ***global_attributes = NULL;
109
0
110
0
/* Attribute ids are 32bit, we split it up like this:
111
0
 * |------------|--------------------|
112
0
 *   12 bit          20 bit
113
0
 *   namespace      attribute id
114
0
 *
115
0
 * This way the attributes gets sorted in namespace order
116
0
 */
117
0
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
 * The exact semantics of what constitutes a backup file are
1658
 * backend-specific. For local files, a file is considered a backup
1659
 * if its name ends with `~` and it is a regular file. This follows
1660
 * the POSIX convention used by text editors such as Emacs.
1661
 *
1662
 * It is an error to call this if the #GFileInfo does not contain
1663
 * %G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP.
1664
 *
1665
 * Returns: %TRUE if file is a backup file, %FALSE otherwise.
1666
 **/
1667
gboolean
1668
g_file_info_get_is_backup (GFileInfo *info)
1669
0
{
1670
0
  GFileAttributeValue *value;
1671
1672
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1673
1674
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP, FALSE);
1675
0
  return _g_file_attribute_value_get_boolean (value);
1676
0
}
1677
1678
/**
1679
 * g_file_info_get_is_symlink:
1680
 * @info: a #GFileInfo.
1681
 *
1682
 * Checks if a file is a symlink.
1683
 *
1684
 * It is an error to call this if the #GFileInfo does not contain
1685
 * %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
1686
 *
1687
 * Returns: %TRUE if the given @info is a symlink.
1688
 **/
1689
gboolean
1690
g_file_info_get_is_symlink (GFileInfo *info)
1691
0
{
1692
0
  GFileAttributeValue *value;
1693
1694
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1695
1696
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK, FALSE);
1697
0
  return _g_file_attribute_value_get_boolean (value);
1698
0
}
1699
1700
/**
1701
 * g_file_info_get_name:
1702
 * @info: a #GFileInfo.
1703
 *
1704
 * Gets the name for a file. This is guaranteed to always be set.
1705
 *
1706
 * It is an error to call this if the #GFileInfo does not contain
1707
 * %G_FILE_ATTRIBUTE_STANDARD_NAME.
1708
 *
1709
 * Returns: (type filename) (not nullable): a string containing the file name.
1710
 **/
1711
const char *
1712
g_file_info_get_name (GFileInfo *info)
1713
0
{
1714
0
  GFileAttributeValue *value;
1715
1716
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1717
1718
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_NAME, NULL);
1719
0
  return _g_file_attribute_value_get_byte_string (value);
1720
0
}
1721
1722
/**
1723
 * g_file_info_get_display_name:
1724
 * @info: a #GFileInfo.
1725
 *
1726
 * Gets a display name for a file. This is guaranteed to always be set.
1727
 *
1728
 * It is an error to call this if the #GFileInfo does not contain
1729
 * %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
1730
 *
1731
 * Returns: (not nullable): a string containing the display name.
1732
 **/
1733
const char *
1734
g_file_info_get_display_name (GFileInfo *info)
1735
0
{
1736
0
  GFileAttributeValue *value;
1737
1738
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1739
1740
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, NULL);
1741
0
  return _g_file_attribute_value_get_string (value);
1742
0
}
1743
1744
/**
1745
 * g_file_info_get_edit_name:
1746
 * @info: a #GFileInfo.
1747
 *
1748
 * Gets the edit name for a file.
1749
 *
1750
 * It is an error to call this if the #GFileInfo does not contain
1751
 * %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
1752
 *
1753
 * Returns: a string containing the edit name.
1754
 **/
1755
const char *
1756
g_file_info_get_edit_name (GFileInfo *info)
1757
0
{
1758
0
  GFileAttributeValue *value;
1759
1760
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1761
1762
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, NULL);
1763
0
  return _g_file_attribute_value_get_string (value);
1764
0
}
1765
1766
/**
1767
 * g_file_info_get_icon:
1768
 * @info: a #GFileInfo.
1769
 *
1770
 * Gets the icon for a file.
1771
 *
1772
 * It is an error to call this if the #GFileInfo does not contain
1773
 * %G_FILE_ATTRIBUTE_STANDARD_ICON.
1774
 *
1775
 * Returns: (nullable) (transfer none): #GIcon for the given @info.
1776
 **/
1777
GIcon *
1778
g_file_info_get_icon (GFileInfo *info)
1779
0
{
1780
0
  GFileAttributeValue *value;
1781
0
  GObject *obj;
1782
1783
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1784
1785
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_ICON, NULL);
1786
1787
0
  obj = _g_file_attribute_value_get_object (value);
1788
0
  if (G_IS_ICON (obj))
1789
0
    return G_ICON (obj);
1790
0
  return NULL;
1791
0
}
1792
1793
/**
1794
 * g_file_info_get_symbolic_icon:
1795
 * @info: a #GFileInfo.
1796
 *
1797
 * Gets the symbolic icon for a file.
1798
 *
1799
 * It is an error to call this if the #GFileInfo does not contain
1800
 * %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
1801
 *
1802
 * Returns: (nullable) (transfer none): #GIcon for the given @info.
1803
 *
1804
 * Since: 2.34
1805
 **/
1806
GIcon *
1807
g_file_info_get_symbolic_icon (GFileInfo *info)
1808
0
{
1809
0
  GFileAttributeValue *value;
1810
0
  GObject *obj;
1811
1812
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1813
1814
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, NULL);
1815
1816
0
  obj = _g_file_attribute_value_get_object (value);
1817
0
  if (G_IS_ICON (obj))
1818
0
    return G_ICON (obj);
1819
0
  return NULL;
1820
0
}
1821
1822
/**
1823
 * g_file_info_get_content_type:
1824
 * @info: a #GFileInfo.
1825
 *
1826
 * Gets the file's content type.
1827
 *
1828
 * It is an error to call this if the #GFileInfo does not contain
1829
 * %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
1830
 *
1831
 * Returns: (nullable): a string containing the file's content type,
1832
 * or %NULL if unknown.
1833
 **/
1834
const char *
1835
g_file_info_get_content_type (GFileInfo *info)
1836
0
{
1837
0
  GFileAttributeValue *value;
1838
1839
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1840
1841
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, NULL);
1842
0
  return _g_file_attribute_value_get_string (value);
1843
0
}
1844
1845
/**
1846
 * g_file_info_get_size:
1847
 * @info: a #GFileInfo.
1848
 *
1849
 * Gets the file's size (in bytes). The size is retrieved through the value of
1850
 * the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute and is converted
1851
 * from #guint64 to #goffset before returning the result.
1852
 *
1853
 * It is an error to call this if the #GFileInfo does not contain
1854
 * %G_FILE_ATTRIBUTE_STANDARD_SIZE.
1855
 *
1856
 * Returns: a #goffset containing the file's size (in bytes).
1857
 **/
1858
goffset
1859
g_file_info_get_size (GFileInfo *info)
1860
0
{
1861
0
  GFileAttributeValue *value;
1862
1863
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1864
1865
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SIZE, (goffset) 0);
1866
0
  return (goffset) _g_file_attribute_value_get_uint64 (value);
1867
0
}
1868
1869
/**
1870
 * g_file_info_get_modification_time:
1871
 * @info: a #GFileInfo.
1872
 * @result: (out caller-allocates): a #GTimeVal.
1873
 *
1874
 * Gets the modification time of the current @info and sets it
1875
 * in @result.
1876
 *
1877
 * It is an error to call this if the #GFileInfo does not contain
1878
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1879
 * provided it will be used too.
1880
 *
1881
 * Deprecated: 2.62: Use g_file_info_get_modification_date_time() instead, as
1882
 *    #GTimeVal is deprecated due to the year 2038 problem.
1883
 **/
1884
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1885
void
1886
g_file_info_get_modification_time (GFileInfo *info,
1887
           GTimeVal  *result)
1888
0
{
1889
0
  static guint32 attr_mtime = 0, attr_mtime_usec;
1890
0
  GFileAttributeValue *value;
1891
1892
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1893
0
  g_return_if_fail (result != NULL);
1894
1895
0
  if (attr_mtime == 0)
1896
0
    {
1897
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1898
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1899
0
    }
1900
1901
0
  value = g_file_info_find_value (info, attr_mtime);
1902
1903
0
  if (G_UNLIKELY (value == NULL))
1904
0
    {
1905
0
      g_critical ("GFileInfo created without " G_FILE_ATTRIBUTE_TIME_MODIFIED);
1906
0
      result->tv_sec = result->tv_usec = 0;
1907
0
      g_return_if_reached ();
1908
0
    }
1909
1910
0
  result->tv_sec = _g_file_attribute_value_get_uint64 (value);
1911
0
  value = g_file_info_find_value (info, attr_mtime_usec);
1912
0
  result->tv_usec = _g_file_attribute_value_get_uint32 (value);
1913
0
}
1914
G_GNUC_END_IGNORE_DEPRECATIONS
1915
1916
/**
1917
 * g_file_info_get_modification_date_time:
1918
 * @info: a #GFileInfo.
1919
 *
1920
 * Gets the modification time of the current @info and returns it as a
1921
 * #GDateTime.
1922
 *
1923
 * It is an error to call this if the #GFileInfo does not contain
1924
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1925
 * provided, the resulting #GDateTime will additionally have microsecond
1926
 * precision.
1927
 *
1928
 * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC must
1929
 * be queried separately using g_file_info_get_attribute_uint32().
1930
 *
1931
 * Returns: (transfer full) (nullable): modification time, or %NULL if unknown
1932
 * Since: 2.62
1933
 */
1934
GDateTime *
1935
g_file_info_get_modification_date_time (GFileInfo *info)
1936
0
{
1937
0
  static guint32 attr_mtime = 0, attr_mtime_usec;
1938
0
  GFileAttributeValue *value, *value_usec;
1939
0
  GDateTime *dt = NULL, *dt2 = NULL;
1940
1941
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1942
1943
0
  if (attr_mtime == 0)
1944
0
    {
1945
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1946
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1947
0
    }
1948
1949
0
  value = g_file_info_find_value (info, attr_mtime);
1950
0
  if (value == NULL)
1951
0
    return NULL;
1952
1953
0
  dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
1954
1955
0
  value_usec = g_file_info_find_value (info, attr_mtime_usec);
1956
0
  if (value_usec == NULL)
1957
0
    return g_steal_pointer (&dt);
1958
1959
0
  dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
1960
0
  g_date_time_unref (dt);
1961
1962
0
  return g_steal_pointer (&dt2);
1963
0
}
1964
1965
/**
1966
 * g_file_info_get_access_date_time:
1967
 * @info: a #GFileInfo.
1968
 *
1969
 * Gets the access time of the current @info and returns it as a
1970
 * #GDateTime.
1971
 *
1972
 * It is an error to call this if the #GFileInfo does not contain
1973
 * %G_FILE_ATTRIBUTE_TIME_ACCESS. If %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC is
1974
 * provided, the resulting #GDateTime will additionally have microsecond
1975
 * precision.
1976
 *
1977
 * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC must
1978
 * be queried separately using g_file_info_get_attribute_uint32().
1979
 *
1980
 * Returns: (transfer full) (nullable): access time, or %NULL if unknown
1981
 * Since: 2.70
1982
 */
1983
GDateTime *
1984
g_file_info_get_access_date_time (GFileInfo *info)
1985
0
{
1986
0
  static guint32 attr_atime = 0, attr_atime_usec;
1987
0
  GFileAttributeValue *value, *value_usec;
1988
0
  GDateTime *dt = NULL, *dt2 = NULL;
1989
1990
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1991
1992
0
  if (attr_atime == 0)
1993
0
    {
1994
0
      attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
1995
0
      attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
1996
0
    }
1997
1998
0
  value = g_file_info_find_value (info, attr_atime);
1999
0
  if (value == NULL)
2000
0
    return NULL;
2001
2002
0
  dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
2003
2004
0
  value_usec = g_file_info_find_value (info, attr_atime_usec);
2005
0
  if (value_usec == NULL)
2006
0
    return g_steal_pointer (&dt);
2007
2008
0
  dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
2009
0
  g_date_time_unref (dt);
2010
2011
0
  return g_steal_pointer (&dt2);
2012
0
}
2013
2014
/**
2015
 * g_file_info_get_creation_date_time:
2016
 * @info: a #GFileInfo.
2017
 *
2018
 * Gets the creation time of the current @info and returns it as a
2019
 * #GDateTime.
2020
 *
2021
 * It is an error to call this if the #GFileInfo does not contain
2022
 * %G_FILE_ATTRIBUTE_TIME_CREATED. If %G_FILE_ATTRIBUTE_TIME_CREATED_USEC is
2023
 * provided, the resulting #GDateTime will additionally have microsecond
2024
 * precision.
2025
 *
2026
 * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC must
2027
 * be queried separately using g_file_info_get_attribute_uint32().
2028
 *
2029
 * Returns: (transfer full) (nullable): creation time, or %NULL if unknown
2030
 * Since: 2.70
2031
 */
2032
GDateTime *
2033
g_file_info_get_creation_date_time (GFileInfo *info)
2034
0
{
2035
0
  static guint32 attr_ctime = 0, attr_ctime_usec;
2036
0
  GFileAttributeValue *value, *value_usec;
2037
0
  GDateTime *dt = NULL, *dt2 = NULL;
2038
2039
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2040
2041
0
  if (attr_ctime == 0)
2042
0
    {
2043
0
      attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2044
0
      attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2045
0
    }
2046
2047
0
  value = g_file_info_find_value (info, attr_ctime);
2048
0
  if (value == NULL)
2049
0
    return NULL;
2050
2051
0
  dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
2052
2053
0
  value_usec = g_file_info_find_value (info, attr_ctime_usec);
2054
0
  if (value_usec == NULL)
2055
0
    return g_steal_pointer (&dt);
2056
2057
0
  dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
2058
0
  g_date_time_unref (dt);
2059
2060
0
  return g_steal_pointer (&dt2);
2061
0
}
2062
2063
/**
2064
 * g_file_info_get_symlink_target:
2065
 * @info: a #GFileInfo.
2066
 *
2067
 * Gets the symlink target for a given #GFileInfo.
2068
 *
2069
 * It is an error to call this if the #GFileInfo does not contain
2070
 * %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET.
2071
 *
2072
 * Returns: (type filename) (nullable): a string containing the symlink target.
2073
 **/
2074
const char *
2075
g_file_info_get_symlink_target (GFileInfo *info)
2076
0
{
2077
0
  GFileAttributeValue *value;
2078
2079
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2080
2081
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, NULL);
2082
0
  return _g_file_attribute_value_get_byte_string (value);
2083
0
}
2084
2085
/**
2086
 * g_file_info_get_etag:
2087
 * @info: a #GFileInfo.
2088
 *
2089
 * Gets the [entity tag][iface@Gio.File#entity-tags] for a given
2090
 * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
2091
 *
2092
 * It is an error to call this if the #GFileInfo does not contain
2093
 * %G_FILE_ATTRIBUTE_ETAG_VALUE.
2094
 *
2095
 * Returns: (nullable): a string containing the value of the "etag:value" attribute.
2096
 **/
2097
const char *
2098
g_file_info_get_etag (GFileInfo *info)
2099
0
{
2100
0
  GFileAttributeValue *value;
2101
2102
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2103
2104
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_ETAG_VALUE, NULL);
2105
0
  return _g_file_attribute_value_get_string (value);
2106
0
}
2107
2108
/**
2109
 * g_file_info_get_sort_order:
2110
 * @info: a #GFileInfo.
2111
 *
2112
 * Gets the value of the sort_order attribute from the #GFileInfo.
2113
 * See %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2114
 *
2115
 * It is an error to call this if the #GFileInfo does not contain
2116
 * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2117
 *
2118
 * Returns: a #gint32 containing the value of the "standard::sort_order" attribute.
2119
 **/
2120
gint32
2121
g_file_info_get_sort_order (GFileInfo *info)
2122
0
{
2123
0
  GFileAttributeValue *value;
2124
2125
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
2126
2127
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 0);
2128
0
  return _g_file_attribute_value_get_int32 (value);
2129
0
}
2130
2131
/* Helper setters: */
2132
/**
2133
 * g_file_info_set_file_type:
2134
 * @info: a #GFileInfo.
2135
 * @type: a #GFileType.
2136
 *
2137
 * Sets the file type in a #GFileInfo to @type.
2138
 * See %G_FILE_ATTRIBUTE_STANDARD_TYPE.
2139
 **/
2140
void
2141
g_file_info_set_file_type (GFileInfo *info,
2142
         GFileType  type)
2143
0
{
2144
0
  static guint32 attr = 0;
2145
0
  GFileAttributeValue *value;
2146
2147
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2148
2149
0
  if (attr == 0)
2150
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
2151
2152
0
  value = g_file_info_create_value (info, attr);
2153
0
  if (value)
2154
0
    _g_file_attribute_value_set_uint32 (value, type);
2155
0
}
2156
2157
/**
2158
 * g_file_info_set_is_hidden:
2159
 * @info: a #GFileInfo.
2160
 * @is_hidden: a #gboolean.
2161
 *
2162
 * Sets the "is_hidden" attribute in a #GFileInfo according to @is_hidden.
2163
 * See %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
2164
 **/
2165
void
2166
g_file_info_set_is_hidden (GFileInfo *info,
2167
         gboolean   is_hidden)
2168
0
{
2169
0
  static guint32 attr = 0;
2170
0
  GFileAttributeValue *value;
2171
2172
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2173
2174
0
  if (attr == 0)
2175
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
2176
2177
0
  value = g_file_info_create_value (info, attr);
2178
0
  if (value)
2179
0
    _g_file_attribute_value_set_boolean (value, is_hidden);
2180
0
}
2181
2182
/**
2183
 * g_file_info_set_is_symlink:
2184
 * @info: a #GFileInfo.
2185
 * @is_symlink: a #gboolean.
2186
 *
2187
 * Sets the "is_symlink" attribute in a #GFileInfo according to @is_symlink.
2188
 * See %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
2189
 **/
2190
void
2191
g_file_info_set_is_symlink (GFileInfo *info,
2192
          gboolean   is_symlink)
2193
0
{
2194
0
  static guint32 attr = 0;
2195
0
  GFileAttributeValue *value;
2196
2197
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2198
2199
0
  if (attr == 0)
2200
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
2201
2202
0
  value = g_file_info_create_value (info, attr);
2203
0
  if (value)
2204
0
    _g_file_attribute_value_set_boolean (value, is_symlink);
2205
0
}
2206
2207
/**
2208
 * g_file_info_set_name:
2209
 * @info: a #GFileInfo.
2210
 * @name: (type filename): a string containing a name.
2211
 *
2212
 * Sets the name attribute for the current #GFileInfo.
2213
 * See %G_FILE_ATTRIBUTE_STANDARD_NAME.
2214
 **/
2215
void
2216
g_file_info_set_name (GFileInfo  *info,
2217
          const char *name)
2218
0
{
2219
0
  static guint32 attr = 0;
2220
0
  GFileAttributeValue *value;
2221
2222
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2223
0
  g_return_if_fail (name != NULL);
2224
2225
0
  if (attr == 0)
2226
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
2227
2228
0
  value = g_file_info_create_value (info, attr);
2229
0
  if (value)
2230
0
    _g_file_attribute_value_set_byte_string (value, name);
2231
0
}
2232
2233
/**
2234
 * g_file_info_set_display_name:
2235
 * @info: a #GFileInfo.
2236
 * @display_name: a string containing a display name.
2237
 *
2238
 * Sets the display name for the current #GFileInfo.
2239
 * See %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
2240
 **/
2241
void
2242
g_file_info_set_display_name (GFileInfo  *info,
2243
            const char *display_name)
2244
0
{
2245
0
  static guint32 attr = 0;
2246
0
  GFileAttributeValue *value;
2247
2248
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2249
0
  g_return_if_fail (display_name != NULL);
2250
2251
0
  if (attr == 0)
2252
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
2253
2254
0
  value = g_file_info_create_value (info, attr);
2255
0
  if (value)
2256
0
    _g_file_attribute_value_set_string (value, display_name);
2257
0
}
2258
2259
/**
2260
 * g_file_info_set_edit_name:
2261
 * @info: a #GFileInfo.
2262
 * @edit_name: a string containing an edit name.
2263
 *
2264
 * Sets the edit name for the current file.
2265
 * See %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
2266
 **/
2267
void
2268
g_file_info_set_edit_name (GFileInfo  *info,
2269
         const char *edit_name)
2270
0
{
2271
0
  static guint32 attr = 0;
2272
0
  GFileAttributeValue *value;
2273
2274
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2275
0
  g_return_if_fail (edit_name != NULL);
2276
2277
0
  if (attr == 0)
2278
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
2279
2280
0
  value = g_file_info_create_value (info, attr);
2281
0
  if (value)
2282
0
    _g_file_attribute_value_set_string (value, edit_name);
2283
0
}
2284
2285
/**
2286
 * g_file_info_set_icon:
2287
 * @info: a #GFileInfo.
2288
 * @icon: a #GIcon.
2289
 *
2290
 * Sets the icon for a given #GFileInfo.
2291
 * See %G_FILE_ATTRIBUTE_STANDARD_ICON.
2292
 **/
2293
void
2294
g_file_info_set_icon (GFileInfo *info,
2295
          GIcon     *icon)
2296
0
{
2297
0
  static guint32 attr = 0;
2298
0
  GFileAttributeValue *value;
2299
2300
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2301
0
  g_return_if_fail (G_IS_ICON (icon));
2302
2303
0
  if (attr == 0)
2304
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
2305
2306
0
  value = g_file_info_create_value (info, attr);
2307
0
  if (value)
2308
0
    _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2309
0
}
2310
2311
/**
2312
 * g_file_info_set_symbolic_icon:
2313
 * @info: a #GFileInfo.
2314
 * @icon: a #GIcon.
2315
 *
2316
 * Sets the symbolic icon for a given #GFileInfo.
2317
 * See %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
2318
 *
2319
 * Since: 2.34
2320
 **/
2321
void
2322
g_file_info_set_symbolic_icon (GFileInfo *info,
2323
                               GIcon     *icon)
2324
0
{
2325
0
  static guint32 attr = 0;
2326
0
  GFileAttributeValue *value;
2327
2328
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2329
0
  g_return_if_fail (G_IS_ICON (icon));
2330
2331
0
  if (attr == 0)
2332
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON);
2333
2334
0
  value = g_file_info_create_value (info, attr);
2335
0
  if (value)
2336
0
    _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2337
0
}
2338
2339
/**
2340
 * g_file_info_set_content_type:
2341
 * @info: a #GFileInfo.
2342
 * @content_type: a [content type](content-types.html#content-types).
2343
 *
2344
 * Sets the content type attribute for a given #GFileInfo.
2345
 * See %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
2346
 **/
2347
void
2348
g_file_info_set_content_type (GFileInfo  *info,
2349
            const char *content_type)
2350
0
{
2351
0
  static guint32 attr = 0;
2352
0
  GFileAttributeValue *value;
2353
2354
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2355
0
  g_return_if_fail (content_type != NULL);
2356
2357
0
  if (attr == 0)
2358
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
2359
2360
0
  value = g_file_info_create_value (info, attr);
2361
0
  if (value)
2362
0
    _g_file_attribute_value_set_string (value, content_type);
2363
0
}
2364
2365
/**
2366
 * g_file_info_set_size:
2367
 * @info: a #GFileInfo.
2368
 * @size: a #goffset containing the file's size.
2369
 *
2370
 * Sets the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in the file info
2371
 * to the given size.
2372
 **/
2373
void
2374
g_file_info_set_size (GFileInfo *info,
2375
          goffset    size)
2376
0
{
2377
0
  static guint32 attr = 0;
2378
0
  GFileAttributeValue *value;
2379
2380
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2381
2382
0
  if (attr == 0)
2383
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
2384
2385
0
  value = g_file_info_create_value (info, attr);
2386
0
  if (value)
2387
0
    _g_file_attribute_value_set_uint64 (value, size);
2388
0
}
2389
2390
/**
2391
 * g_file_info_set_modification_time:
2392
 * @info: a #GFileInfo.
2393
 * @mtime: a #GTimeVal.
2394
 *
2395
 * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2396
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2397
 * given time value.
2398
 *
2399
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2400
 *
2401
 * Deprecated: 2.62: Use g_file_info_set_modification_date_time() instead, as
2402
 *    #GTimeVal is deprecated due to the year 2038 problem.
2403
 **/
2404
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2405
void
2406
g_file_info_set_modification_time (GFileInfo *info,
2407
           GTimeVal  *mtime)
2408
0
{
2409
0
  static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2410
0
  GFileAttributeValue *value;
2411
2412
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2413
0
  g_return_if_fail (mtime != NULL);
2414
2415
0
  if (attr_mtime == 0)
2416
0
    {
2417
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2418
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2419
0
      attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2420
0
    }
2421
2422
0
  value = g_file_info_create_value (info, attr_mtime);
2423
0
  if (value)
2424
0
    _g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
2425
0
  value = g_file_info_create_value (info, attr_mtime_usec);
2426
0
  if (value)
2427
0
    _g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
2428
2429
  /* nsecs can’t be known from a #GTimeVal, so remove them */
2430
0
  g_file_info_remove_value (info, attr_mtime_nsec);
2431
0
}
2432
G_GNUC_END_IGNORE_DEPRECATIONS
2433
2434
/**
2435
 * g_file_info_set_modification_date_time:
2436
 * @info: a #GFileInfo.
2437
 * @mtime: (not nullable): a #GDateTime.
2438
 *
2439
 * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2440
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2441
 * given date/time value.
2442
 *
2443
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2444
 *
2445
 * Since: 2.62
2446
 */
2447
void
2448
g_file_info_set_modification_date_time (GFileInfo *info,
2449
                                        GDateTime *mtime)
2450
0
{
2451
0
  static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2452
0
  GFileAttributeValue *value;
2453
2454
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2455
0
  g_return_if_fail (mtime != NULL);
2456
2457
0
  if (attr_mtime == 0)
2458
0
    {
2459
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2460
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2461
0
      attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2462
0
    }
2463
2464
0
  value = g_file_info_create_value (info, attr_mtime);
2465
0
  if (value)
2466
0
    _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (mtime));
2467
0
  value = g_file_info_create_value (info, attr_mtime_usec);
2468
0
  if (value)
2469
0
    _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (mtime));
2470
2471
  /* nsecs can’t be known from a #GDateTime, so remove them */
2472
0
  g_file_info_remove_value (info, attr_mtime_nsec);
2473
0
}
2474
2475
/**
2476
 * g_file_info_set_access_date_time:
2477
 * @info: a #GFileInfo.
2478
 * @atime: (not nullable): a #GDateTime.
2479
 *
2480
 * Sets the %G_FILE_ATTRIBUTE_TIME_ACCESS and
2481
 * %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC attributes in the file info to the
2482
 * given date/time value.
2483
 *
2484
 * %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC will be cleared.
2485
 *
2486
 * Since: 2.70
2487
 */
2488
void
2489
g_file_info_set_access_date_time (GFileInfo *info,
2490
                                  GDateTime *atime)
2491
0
{
2492
0
  static guint32 attr_atime = 0, attr_atime_usec = 0, attr_atime_nsec = 0;
2493
0
  GFileAttributeValue *value;
2494
2495
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2496
0
  g_return_if_fail (atime != NULL);
2497
2498
0
  if (attr_atime == 0)
2499
0
    {
2500
0
      attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
2501
0
      attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
2502
0
      attr_atime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
2503
0
    }
2504
2505
0
  value = g_file_info_create_value (info, attr_atime);
2506
0
  if (value)
2507
0
    _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (atime));
2508
0
  value = g_file_info_create_value (info, attr_atime_usec);
2509
0
  if (value)
2510
0
    _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (atime));
2511
2512
  /* nsecs can’t be known from a #GDateTime, so remove them */
2513
0
  g_file_info_remove_value (info, attr_atime_nsec);
2514
0
}
2515
2516
/**
2517
 * g_file_info_set_creation_date_time:
2518
 * @info: a #GFileInfo.
2519
 * @creation_time: (not nullable): a #GDateTime.
2520
 *
2521
 * Sets the %G_FILE_ATTRIBUTE_TIME_CREATED and
2522
 * %G_FILE_ATTRIBUTE_TIME_CREATED_USEC attributes in the file info to the
2523
 * given date/time value.
2524
 *
2525
 * %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC will be cleared.
2526
 *
2527
 * Since: 2.70
2528
 */
2529
void
2530
g_file_info_set_creation_date_time (GFileInfo *info,
2531
                                    GDateTime *creation_time)
2532
0
{
2533
0
  static guint32 attr_ctime = 0, attr_ctime_usec = 0, attr_ctime_nsec = 0;
2534
0
  GFileAttributeValue *value;
2535
2536
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2537
0
  g_return_if_fail (creation_time != NULL);
2538
2539
0
  if (attr_ctime == 0)
2540
0
    {
2541
0
      attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2542
0
      attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2543
0
      attr_ctime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
2544
0
    }
2545
2546
0
  value = g_file_info_create_value (info, attr_ctime);
2547
0
  if (value)
2548
0
    _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (creation_time));
2549
0
  value = g_file_info_create_value (info, attr_ctime_usec);
2550
0
  if (value)
2551
0
    _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (creation_time));
2552
2553
  /* nsecs can’t be known from a #GDateTime, so remove them */
2554
0
  g_file_info_remove_value (info, attr_ctime_nsec);
2555
0
}
2556
2557
/**
2558
 * g_file_info_set_symlink_target:
2559
 * @info: a #GFileInfo.
2560
 * @symlink_target: (type filename): a static string containing a path to a symlink target.
2561
 *
2562
 * Sets the %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET attribute in the file info
2563
 * to the given symlink target.
2564
 **/
2565
void
2566
g_file_info_set_symlink_target (GFileInfo  *info,
2567
        const char *symlink_target)
2568
0
{
2569
0
  static guint32 attr = 0;
2570
0
  GFileAttributeValue *value;
2571
2572
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2573
0
  g_return_if_fail (symlink_target != NULL);
2574
2575
0
  if (attr == 0)
2576
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
2577
2578
0
  value = g_file_info_create_value (info, attr);
2579
0
  if (value)
2580
0
    _g_file_attribute_value_set_byte_string (value, symlink_target);
2581
0
}
2582
2583
/**
2584
 * g_file_info_set_sort_order:
2585
 * @info: a #GFileInfo.
2586
 * @sort_order: a sort order integer.
2587
 *
2588
 * Sets the sort order attribute in the file info structure. See
2589
 * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2590
 **/
2591
void
2592
g_file_info_set_sort_order (GFileInfo *info,
2593
          gint32     sort_order)
2594
0
{
2595
0
  static guint32 attr = 0;
2596
0
  GFileAttributeValue *value;
2597
2598
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2599
2600
0
  if (attr == 0)
2601
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
2602
2603
0
  value = g_file_info_create_value (info, attr);
2604
0
  if (value)
2605
0
    _g_file_attribute_value_set_int32 (value, sort_order);
2606
0
}
2607
2608
2609
typedef struct {
2610
  guint32 id;
2611
  guint32 mask;
2612
} SubMatcher;
2613
2614
struct _GFileAttributeMatcher {
2615
  gboolean all;
2616
  gint ref;
2617
2618
  GArray *sub_matchers;
2619
2620
  /* Iterator */
2621
  guint32 iterator_ns;
2622
  gint iterator_pos;
2623
};
2624
2625
0
G_DEFINE_BOXED_TYPE (GFileAttributeMatcher, g_file_attribute_matcher,
2626
0
                     g_file_attribute_matcher_ref,
2627
0
                     g_file_attribute_matcher_unref)
2628
0
2629
0
static gint
2630
0
compare_sub_matchers (gconstpointer a,
2631
0
                      gconstpointer b)
2632
0
{
2633
0
  const SubMatcher *suba = a;
2634
0
  const SubMatcher *subb = b;
2635
0
  int diff;
2636
2637
0
  diff = suba->id - subb->id;
2638
2639
0
  if (diff)
2640
0
    return diff;
2641
2642
0
  return suba->mask - subb->mask;
2643
0
}
2644
2645
static gboolean
2646
sub_matcher_matches (SubMatcher *matcher,
2647
                     SubMatcher *submatcher)
2648
0
{
2649
0
  if ((matcher->mask & submatcher->mask) != matcher->mask)
2650
0
    return FALSE;
2651
  
2652
0
  return matcher->id == (submatcher->id & matcher->mask);
2653
0
}
2654
2655
/* Call this function after modifying a matcher.
2656
 * It will ensure all the invariants other functions rely on.
2657
 */
2658
static GFileAttributeMatcher *
2659
matcher_optimize (GFileAttributeMatcher *matcher)
2660
0
{
2661
0
  SubMatcher *submatcher, *compare;
2662
0
  guint i, j;
2663
2664
  /* remove sub_matchers if we match everything anyway */
2665
0
  if (matcher->all)
2666
0
    {
2667
0
      if (matcher->sub_matchers)
2668
0
        {
2669
0
          g_array_free (matcher->sub_matchers, TRUE);
2670
0
          matcher->sub_matchers = NULL;
2671
0
        }
2672
0
      return matcher;
2673
0
    }
2674
2675
0
  if (matcher->sub_matchers->len == 0)
2676
0
    {
2677
0
      g_file_attribute_matcher_unref (matcher);
2678
0
      return NULL;
2679
0
    }
2680
2681
  /* sort sub_matchers by id (and then mask), so we can bsearch
2682
   * and compare matchers in O(N) instead of O(N²) */
2683
0
  g_array_sort (matcher->sub_matchers, compare_sub_matchers);
2684
2685
  /* remove duplicates and specific matches when we match the whole namespace */
2686
0
  j = 0;
2687
0
  compare = &g_array_index (matcher->sub_matchers, SubMatcher, j);
2688
2689
0
  for (i = 1; i < matcher->sub_matchers->len; i++)
2690
0
    {
2691
0
      submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
2692
0
      if (sub_matcher_matches (compare, submatcher))
2693
0
        continue;
2694
2695
0
      j++;
2696
0
      compare++;
2697
2698
0
      if (j < i)
2699
0
        *compare = *submatcher;
2700
0
    }
2701
2702
0
  g_array_set_size (matcher->sub_matchers, j + 1);
2703
2704
0
  return matcher;
2705
0
}
2706
2707
/**
2708
 * g_file_attribute_matcher_new:
2709
 * @attributes: an attribute string to match.
2710
 *
2711
 * Creates a new file attribute matcher, which matches attributes
2712
 * against a given string. [GFileAttributeMatchers][struct@FileAttributeMatcher] are reference
2713
 * counted structures, and are created with a reference count of 1. If
2714
 * the number of references falls to 0, the [struct@FileAttributeMatcher] is
2715
 * automatically destroyed.
2716
 *
2717
 * The @attributes string should be formatted with specific keys separated
2718
 * from namespaces with a double colon. Several `"namespace::key"` strings may be
2719
 * concatenated with a single comma (e.g. `"standard::type,standard::is-hidden"`).
2720
 * The wildcard `"*"` may be used to match all keys and namespaces, or
2721
 * `"namespace::*"` will match all keys in a given namespace.
2722
 *
2723
 * ## Examples of file attribute matcher strings and results
2724
 *
2725
 * - `"*"`: matches all attributes.
2726
 * - `"standard::is-hidden"`: matches only the key is-hidden in the
2727
 *   standard namespace.
2728
 * - `"standard::type,unix::*"`: matches the type key in the standard
2729
 *   namespace and all keys in the unix namespace.
2730
 *
2731
 * Returns: a #GFileAttributeMatcher
2732
 */
2733
GFileAttributeMatcher *
2734
g_file_attribute_matcher_new (const char *attributes)
2735
0
{
2736
0
  char **split;
2737
0
  char *colon;
2738
0
  int i;
2739
0
  GFileAttributeMatcher *matcher;
2740
2741
0
  if (attributes == NULL || *attributes == '\0')
2742
0
    return NULL;
2743
2744
0
  matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
2745
0
  matcher->ref = 1;
2746
0
  matcher->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2747
2748
0
  split = g_strsplit (attributes, ",", -1);
2749
2750
0
  for (i = 0; split[i] != NULL; i++)
2751
0
    {
2752
0
      if (strcmp (split[i], "*") == 0)
2753
0
  matcher->all = TRUE;
2754
0
      else
2755
0
  {
2756
0
          SubMatcher s;
2757
2758
0
    colon = strstr (split[i], "::");
2759
0
    if (colon != NULL &&
2760
0
        !(colon[2] == 0 ||
2761
0
    (colon[2] == '*' &&
2762
0
     colon[3] == 0)))
2763
0
      {
2764
0
        s.id = lookup_attribute (split[i]);
2765
0
        s.mask = 0xffffffff;
2766
0
      }
2767
0
    else
2768
0
      {
2769
0
        if (colon)
2770
0
    *colon = 0;
2771
2772
0
        s.id = lookup_namespace (split[i]) << NS_POS;
2773
0
        s.mask = NS_MASK << NS_POS;
2774
0
      }
2775
2776
0
          g_array_append_val (matcher->sub_matchers, s);
2777
0
  }
2778
0
    }
2779
2780
0
  g_strfreev (split);
2781
2782
0
  matcher = matcher_optimize (matcher);
2783
2784
0
  return matcher;
2785
0
}
2786
2787
/**
2788
 * g_file_attribute_matcher_subtract:
2789
 * @matcher: (nullable): Matcher to subtract from 
2790
 * @subtract: (nullable): The matcher to subtract
2791
 *
2792
 * Subtracts all attributes of @subtract from @matcher and returns
2793
 * a matcher that supports those attributes.
2794
 *
2795
 * Note that currently it is not possible to remove a single
2796
 * attribute when the @matcher matches the whole namespace - or remove
2797
 * a namespace or attribute when the matcher matches everything. This
2798
 * is a limitation of the current implementation, but may be fixed
2799
 * in the future.
2800
 *
2801
 * Returns: (nullable): A file attribute matcher matching all attributes of
2802
 *     @matcher that are not matched by @subtract
2803
 **/
2804
GFileAttributeMatcher *
2805
g_file_attribute_matcher_subtract (GFileAttributeMatcher *matcher,
2806
                                   GFileAttributeMatcher *subtract)
2807
0
{
2808
0
  GFileAttributeMatcher *result;
2809
0
  guint mi, si;
2810
0
  SubMatcher *msub, *ssub;
2811
2812
0
  if (matcher == NULL)
2813
0
    return NULL;
2814
0
  if (subtract == NULL)
2815
0
    return g_file_attribute_matcher_ref (matcher);
2816
0
  if (subtract->all)
2817
0
    return NULL;
2818
0
  if (matcher->all)
2819
0
    return g_file_attribute_matcher_ref (matcher);
2820
2821
0
  result = g_malloc0 (sizeof (GFileAttributeMatcher));
2822
0
  result->ref = 1;
2823
0
  result->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2824
2825
0
  si = 0;
2826
0
  g_assert (subtract->sub_matchers->len > 0);
2827
0
  ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2828
2829
0
  for (mi = 0; mi < matcher->sub_matchers->len; mi++)
2830
0
    {
2831
0
      msub = &g_array_index (matcher->sub_matchers, SubMatcher, mi);
2832
2833
0
retry:
2834
0
      if (sub_matcher_matches (ssub, msub))
2835
0
        continue;
2836
2837
0
      si++;
2838
0
      if (si >= subtract->sub_matchers->len)
2839
0
        break;
2840
2841
0
      ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2842
0
      if (ssub->id <= msub->id)
2843
0
        goto retry;
2844
2845
0
      g_array_append_val (result->sub_matchers, *msub);
2846
0
    }
2847
2848
0
  if (mi < matcher->sub_matchers->len)
2849
0
    g_array_append_vals (result->sub_matchers,
2850
0
                         &g_array_index (matcher->sub_matchers, SubMatcher, mi),
2851
0
                         matcher->sub_matchers->len - mi);
2852
2853
0
  result = matcher_optimize (result);
2854
2855
0
  return result;
2856
0
}
2857
2858
/**
2859
 * g_file_attribute_matcher_ref:
2860
 * @matcher: a #GFileAttributeMatcher.
2861
 *
2862
 * References a file attribute matcher.
2863
 *
2864
 * Returns: a #GFileAttributeMatcher.
2865
 **/
2866
GFileAttributeMatcher *
2867
g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
2868
0
{
2869
0
  if (matcher)
2870
0
    {
2871
0
      g_return_val_if_fail (matcher->ref > 0, NULL);
2872
0
      g_atomic_int_inc (&matcher->ref);
2873
0
    }
2874
0
  return matcher;
2875
0
}
2876
2877
/**
2878
 * g_file_attribute_matcher_unref:
2879
 * @matcher: a #GFileAttributeMatcher.
2880
 *
2881
 * Unreferences @matcher. If the reference count falls below 1,
2882
 * the @matcher is automatically freed.
2883
 *
2884
 **/
2885
void
2886
g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
2887
0
{
2888
0
  if (matcher)
2889
0
    {
2890
0
      g_return_if_fail (matcher->ref > 0);
2891
2892
0
      if (g_atomic_int_dec_and_test (&matcher->ref))
2893
0
  {
2894
0
    if (matcher->sub_matchers)
2895
0
      g_array_free (matcher->sub_matchers, TRUE);
2896
2897
0
    g_free (matcher);
2898
0
  }
2899
0
    }
2900
0
}
2901
2902
/**
2903
 * g_file_attribute_matcher_matches_only:
2904
 * @matcher: a #GFileAttributeMatcher.
2905
 * @attribute: a file attribute key.
2906
 *
2907
 * Checks if an attribute matcher only matches a given attribute. Always
2908
 * returns %FALSE if "*" was used when creating the matcher.
2909
 *
2910
 * Returns: %TRUE if the matcher only matches @attribute. %FALSE otherwise.
2911
 **/
2912
gboolean
2913
g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
2914
               const char            *attribute)
2915
0
{
2916
0
  SubMatcher *sub_matcher;
2917
0
  guint32 id;
2918
2919
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2920
2921
0
  if (matcher == NULL ||
2922
0
      matcher->all)
2923
0
    return FALSE;
2924
2925
0
  if (matcher->sub_matchers->len != 1)
2926
0
    return FALSE;
2927
  
2928
0
  id = lookup_attribute (attribute);
2929
  
2930
0
  sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, 0);
2931
  
2932
0
  return sub_matcher->id == id &&
2933
0
         sub_matcher->mask == 0xffffffff;
2934
0
}
2935
2936
static gboolean
2937
matcher_matches_id (GFileAttributeMatcher *matcher,
2938
                    guint32                id)
2939
0
{
2940
0
  SubMatcher *sub_matchers;
2941
0
  guint i;
2942
2943
0
  if (matcher->sub_matchers)
2944
0
    {
2945
0
      sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
2946
0
      for (i = 0; i < matcher->sub_matchers->len; i++)
2947
0
  {
2948
0
    if (sub_matchers[i].id == (id & sub_matchers[i].mask))
2949
0
      return TRUE;
2950
0
  }
2951
0
    }
2952
2953
0
  return FALSE;
2954
0
}
2955
2956
gboolean
2957
_g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
2958
                                      guint32                id)
2959
0
{
2960
  /* We return a NULL matcher for an empty match string, so handle this */
2961
0
  if (matcher == NULL)
2962
0
    return FALSE;
2963
2964
0
  if (matcher->all)
2965
0
    return TRUE;
2966
2967
0
  return matcher_matches_id (matcher, id);
2968
0
}
2969
2970
/**
2971
 * g_file_attribute_matcher_matches:
2972
 * @matcher: a #GFileAttributeMatcher.
2973
 * @attribute: a file attribute key.
2974
 *
2975
 * Checks if an attribute will be matched by an attribute matcher. If
2976
 * the matcher was created with the "*" matching string, this function
2977
 * will always return %TRUE.
2978
 *
2979
 * Returns: %TRUE if @attribute matches @matcher. %FALSE otherwise.
2980
 **/
2981
gboolean
2982
g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
2983
          const char            *attribute)
2984
0
{
2985
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2986
2987
  /* We return a NULL matcher for an empty match string, so handle this */
2988
0
  if (matcher == NULL)
2989
0
    return FALSE;
2990
2991
0
  if (matcher->all)
2992
0
    return TRUE;
2993
2994
0
  return matcher_matches_id (matcher, lookup_attribute (attribute));
2995
0
}
2996
2997
/* return TRUE -> all */
2998
/**
2999
 * g_file_attribute_matcher_enumerate_namespace:
3000
 * @matcher: a #GFileAttributeMatcher.
3001
 * @ns: a string containing a file attribute namespace.
3002
 *
3003
 * Checks if the matcher will match all of the keys in a given namespace.
3004
 * This will always return %TRUE if a wildcard character is in use (e.g. if
3005
 * matcher was created with "standard::\*" and @ns is "standard", or if matcher was created
3006
 * using "*" and namespace is anything.)
3007
 *
3008
 * TODO: this is awkwardly worded.
3009
 *
3010
 * Returns: %TRUE if the matcher matches all of the entries
3011
 * in the given @ns, %FALSE otherwise.
3012
 **/
3013
gboolean
3014
g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
3015
                const char            *ns)
3016
0
{
3017
0
  SubMatcher *sub_matchers;
3018
0
  guint ns_id;
3019
0
  guint i;
3020
3021
0
  g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
3022
3023
  /* We return a NULL matcher for an empty match string, so handle this */
3024
0
  if (matcher == NULL)
3025
0
    return FALSE;
3026
3027
0
  if (matcher->all)
3028
0
    return TRUE;
3029
3030
0
  ns_id = lookup_namespace (ns) << NS_POS;
3031
3032
0
  if (matcher->sub_matchers)
3033
0
    {
3034
0
      sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
3035
0
      for (i = 0; i < matcher->sub_matchers->len; i++)
3036
0
  {
3037
0
    if (sub_matchers[i].id == ns_id)
3038
0
      return TRUE;
3039
0
  }
3040
0
    }
3041
3042
0
  matcher->iterator_ns = ns_id;
3043
0
  matcher->iterator_pos = 0;
3044
3045
0
  return FALSE;
3046
0
}
3047
3048
/**
3049
 * g_file_attribute_matcher_enumerate_next:
3050
 * @matcher: a #GFileAttributeMatcher.
3051
 *
3052
 * Gets the next matched attribute from a #GFileAttributeMatcher.
3053
 *
3054
 * Returns: (nullable): a string containing the next attribute or, %NULL if
3055
 * no more attribute exist.
3056
 **/
3057
const char *
3058
g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
3059
0
{
3060
0
  guint i;
3061
0
  SubMatcher *sub_matcher;
3062
3063
  /* We return a NULL matcher for an empty match string, so handle this */
3064
0
  if (matcher == NULL)
3065
0
    return NULL;
3066
3067
0
  while (1)
3068
0
    {
3069
0
      i = matcher->iterator_pos++;
3070
3071
0
      if (matcher->sub_matchers == NULL)
3072
0
        return NULL;
3073
3074
0
      if (i < matcher->sub_matchers->len)
3075
0
        sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3076
0
      else
3077
0
        return NULL;
3078
3079
0
      if (sub_matcher->mask == 0xffffffff &&
3080
0
    (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
3081
0
  return get_attribute_for_id (sub_matcher->id);
3082
0
    }
3083
0
}
3084
3085
/**
3086
 * g_file_attribute_matcher_to_string:
3087
 * @matcher: (nullable): a #GFileAttributeMatcher.
3088
 *
3089
 * Prints what the matcher is matching against. The format will be 
3090
 * equal to the format passed to g_file_attribute_matcher_new().
3091
 * The output however, might not be identical, as the matcher may
3092
 * decide to use a different order or omit needless parts.
3093
 *
3094
 * Returns: a string describing the attributes the matcher matches
3095
 *   against or %NULL if @matcher was %NULL.
3096
 *
3097
 * Since: 2.32
3098
 **/
3099
char *
3100
g_file_attribute_matcher_to_string (GFileAttributeMatcher *matcher)
3101
0
{
3102
0
  GString *string;
3103
0
  guint i;
3104
3105
0
  if (matcher == NULL)
3106
0
    return NULL;
3107
3108
0
  if (matcher->all)
3109
0
    return g_strdup ("*");
3110
3111
0
  string = g_string_new ("");
3112
0
  for (i = 0; i < matcher->sub_matchers->len; i++)
3113
0
    {
3114
0
      SubMatcher *submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3115
3116
0
      if (i > 0)
3117
0
        g_string_append_c (string, ',');
3118
3119
0
      g_string_append (string, get_attribute_for_id (submatcher->id));
3120
0
    }
3121
3122
0
  return g_string_free (string, FALSE);
3123
0
}