Coverage Report

Created: 2025-07-18 06:08

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