Merge branch 'test-ip_mreq_source-android-only' into 'master'
[glib.git] / gio / gfileinfo.c
bloba595c6f4a05b2c36177d696dfe70ea4356ce6c4a
1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Alexander Larsson <alexl@redhat.com>
21 /**
22 * SECTION:gfileinfo
23 * @short_description: File Information and Attributes
24 * @include: gio/gio.h
25 * @see_also: #GFile, [GFileAttribute][gio-GFileAttribute]
27 * Functionality for manipulating basic metadata for files. #GFileInfo
28 * implements methods for getting information that all files should
29 * contain, and allows for manipulation of extended attributes.
31 * See [GFileAttribute][gio-GFileAttribute] for more information on how
32 * GIO handles file attributes.
34 * To obtain a #GFileInfo for a #GFile, use g_file_query_info() (or its
35 * async variant). To obtain a #GFileInfo for a file input or output
36 * stream, use g_file_input_stream_query_info() or
37 * g_file_output_stream_query_info() (or their async variants).
39 * To change the actual attributes of a file, you should then set the
40 * attribute in the #GFileInfo and call g_file_set_attributes_from_info()
41 * or g_file_set_attributes_async() on a GFile.
43 * However, not all attributes can be changed in the file. For instance,
44 * the actual size of a file cannot be changed via g_file_info_set_size().
45 * You may call g_file_query_settable_attributes() and
46 * g_file_query_writable_namespaces() to discover the settable attributes
47 * of a particular file at runtime.
49 * #GFileAttributeMatcher allows for searching through a #GFileInfo for
50 * attributes.
51 **/
53 #include "config.h"
55 #include <string.h>
57 #include "gfileinfo.h"
58 #include "gfileinfo-priv.h"
59 #include "gfileattribute-priv.h"
60 #include "gicon.h"
61 #include "glibintl.h"
64 /* We use this nasty thing, because NULL is a valid attribute matcher (matches nothing) */
65 #define NO_ATTRIBUTE_MASK ((GFileAttributeMatcher *)1)
67 typedef struct {
68 guint32 attribute;
69 GFileAttributeValue value;
70 } GFileAttribute;
72 struct _GFileInfo
74 GObject parent_instance;
76 GArray *attributes;
77 GFileAttributeMatcher *mask;
80 struct _GFileInfoClass
82 GObjectClass parent_class;
86 G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT)
88 typedef struct {
89 guint32 id;
90 guint32 attribute_id_counter;
91 } NSInfo;
93 G_LOCK_DEFINE_STATIC (attribute_hash);
94 static int namespace_id_counter = 0;
95 static GHashTable *ns_hash = NULL;
96 static GHashTable *attribute_hash = NULL;
97 static char ***attributes = NULL;
99 /* Attribute ids are 32bit, we split it up like this:
100 * |------------|--------------------|
101 * 12 bit 20 bit
102 * namespace attribute id
104 * This way the attributes gets sorted in namespace order
107 #define NS_POS 20
108 #define NS_MASK ((guint32)((1<<12) - 1))
109 #define ID_POS 0
110 #define ID_MASK ((guint32)((1<<20) - 1))
112 #define GET_NS(_attr_id) \
113 (((guint32) (_attr_id) >> NS_POS) & NS_MASK)
114 #define GET_ID(_attr_id) \
115 (((guint32)(_attr_id) >> ID_POS) & ID_MASK)
117 #define MAKE_ATTR_ID(_ns, _id) \
118 ( ((((guint32) _ns) & NS_MASK) << NS_POS) | \
119 ((((guint32) _id) & ID_MASK) << ID_POS) )
121 static NSInfo *
122 _lookup_namespace (const char *namespace)
124 NSInfo *ns_info;
126 ns_info = g_hash_table_lookup (ns_hash, namespace);
127 if (ns_info == NULL)
129 ns_info = g_new0 (NSInfo, 1);
130 ns_info->id = ++namespace_id_counter;
131 g_hash_table_insert (ns_hash, g_strdup (namespace), ns_info);
132 attributes = g_realloc (attributes, (ns_info->id + 1) * sizeof (char **));
133 attributes[ns_info->id] = g_new (char *, 1);
134 attributes[ns_info->id][0] = g_strconcat (namespace, "::*", NULL);
136 return ns_info;
139 static guint32
140 _lookup_attribute (const char *attribute)
142 guint32 attr_id, id;
143 char *ns;
144 const char *colon;
145 NSInfo *ns_info;
147 attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute));
149 if (attr_id != 0)
150 return attr_id;
152 colon = strstr (attribute, "::");
153 if (colon)
154 ns = g_strndup (attribute, colon - attribute);
155 else
156 ns = g_strdup ("");
158 ns_info = _lookup_namespace (ns);
159 g_free (ns);
161 id = ++ns_info->attribute_id_counter;
162 attributes[ns_info->id] = g_realloc (attributes[ns_info->id], (id + 1) * sizeof (char *));
163 attributes[ns_info->id][id] = g_strdup (attribute);
165 attr_id = MAKE_ATTR_ID (ns_info->id, id);
167 g_hash_table_insert (attribute_hash, attributes[ns_info->id][id], GUINT_TO_POINTER (attr_id));
169 return attr_id;
172 static void
173 ensure_attribute_hash (void)
175 if (attribute_hash != NULL)
176 return;
178 ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
179 attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
181 #define REGISTER_ATTRIBUTE(name) G_STMT_START{\
182 guint _u = _lookup_attribute (G_FILE_ATTRIBUTE_ ## name); \
183 /* use for generating the ID: g_print ("#define G_FILE_ATTRIBUTE_ID_%s (%u + %u)\n", #name + 17, _u & ~ID_MASK, _u & ID_MASK); */ \
184 g_assert (_u == G_FILE_ATTRIBUTE_ID_ ## name); \
185 }G_STMT_END
187 REGISTER_ATTRIBUTE (STANDARD_TYPE);
188 REGISTER_ATTRIBUTE (STANDARD_IS_HIDDEN);
189 REGISTER_ATTRIBUTE (STANDARD_IS_BACKUP);
190 REGISTER_ATTRIBUTE (STANDARD_IS_SYMLINK);
191 REGISTER_ATTRIBUTE (STANDARD_IS_VIRTUAL);
192 REGISTER_ATTRIBUTE (STANDARD_NAME);
193 REGISTER_ATTRIBUTE (STANDARD_DISPLAY_NAME);
194 REGISTER_ATTRIBUTE (STANDARD_EDIT_NAME);
195 REGISTER_ATTRIBUTE (STANDARD_COPY_NAME);
196 REGISTER_ATTRIBUTE (STANDARD_DESCRIPTION);
197 REGISTER_ATTRIBUTE (STANDARD_ICON);
198 REGISTER_ATTRIBUTE (STANDARD_CONTENT_TYPE);
199 REGISTER_ATTRIBUTE (STANDARD_FAST_CONTENT_TYPE);
200 REGISTER_ATTRIBUTE (STANDARD_SIZE);
201 REGISTER_ATTRIBUTE (STANDARD_ALLOCATED_SIZE);
202 REGISTER_ATTRIBUTE (STANDARD_SYMLINK_TARGET);
203 REGISTER_ATTRIBUTE (STANDARD_TARGET_URI);
204 REGISTER_ATTRIBUTE (STANDARD_SORT_ORDER);
205 REGISTER_ATTRIBUTE (STANDARD_SYMBOLIC_ICON);
206 REGISTER_ATTRIBUTE (STANDARD_IS_VOLATILE);
207 REGISTER_ATTRIBUTE (ETAG_VALUE);
208 REGISTER_ATTRIBUTE (ID_FILE);
209 REGISTER_ATTRIBUTE (ID_FILESYSTEM);
210 REGISTER_ATTRIBUTE (ACCESS_CAN_READ);
211 REGISTER_ATTRIBUTE (ACCESS_CAN_WRITE);
212 REGISTER_ATTRIBUTE (ACCESS_CAN_EXECUTE);
213 REGISTER_ATTRIBUTE (ACCESS_CAN_DELETE);
214 REGISTER_ATTRIBUTE (ACCESS_CAN_TRASH);
215 REGISTER_ATTRIBUTE (ACCESS_CAN_RENAME);
216 REGISTER_ATTRIBUTE (MOUNTABLE_CAN_MOUNT);
217 REGISTER_ATTRIBUTE (MOUNTABLE_CAN_UNMOUNT);
218 REGISTER_ATTRIBUTE (MOUNTABLE_CAN_EJECT);
219 REGISTER_ATTRIBUTE (MOUNTABLE_UNIX_DEVICE);
220 REGISTER_ATTRIBUTE (MOUNTABLE_UNIX_DEVICE_FILE);
221 REGISTER_ATTRIBUTE (MOUNTABLE_HAL_UDI);
222 REGISTER_ATTRIBUTE (MOUNTABLE_CAN_START);
223 REGISTER_ATTRIBUTE (MOUNTABLE_CAN_START_DEGRADED);
224 REGISTER_ATTRIBUTE (MOUNTABLE_CAN_STOP);
225 REGISTER_ATTRIBUTE (MOUNTABLE_START_STOP_TYPE);
226 REGISTER_ATTRIBUTE (MOUNTABLE_CAN_POLL);
227 REGISTER_ATTRIBUTE (MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC);
228 REGISTER_ATTRIBUTE (TIME_MODIFIED);
229 REGISTER_ATTRIBUTE (TIME_MODIFIED_USEC);
230 REGISTER_ATTRIBUTE (TIME_ACCESS);
231 REGISTER_ATTRIBUTE (TIME_ACCESS_USEC);
232 REGISTER_ATTRIBUTE (TIME_CHANGED);
233 REGISTER_ATTRIBUTE (TIME_CHANGED_USEC);
234 REGISTER_ATTRIBUTE (TIME_CREATED);
235 REGISTER_ATTRIBUTE (TIME_CREATED_USEC);
236 REGISTER_ATTRIBUTE (UNIX_DEVICE);
237 REGISTER_ATTRIBUTE (UNIX_INODE);
238 REGISTER_ATTRIBUTE (UNIX_MODE);
239 REGISTER_ATTRIBUTE (UNIX_NLINK);
240 REGISTER_ATTRIBUTE (UNIX_UID);
241 REGISTER_ATTRIBUTE (UNIX_GID);
242 REGISTER_ATTRIBUTE (UNIX_RDEV);
243 REGISTER_ATTRIBUTE (UNIX_BLOCK_SIZE);
244 REGISTER_ATTRIBUTE (UNIX_BLOCKS);
245 REGISTER_ATTRIBUTE (UNIX_IS_MOUNTPOINT);
246 REGISTER_ATTRIBUTE (DOS_IS_ARCHIVE);
247 REGISTER_ATTRIBUTE (DOS_IS_SYSTEM);
248 REGISTER_ATTRIBUTE (OWNER_USER);
249 REGISTER_ATTRIBUTE (OWNER_USER_REAL);
250 REGISTER_ATTRIBUTE (OWNER_GROUP);
251 REGISTER_ATTRIBUTE (THUMBNAIL_PATH);
252 REGISTER_ATTRIBUTE (THUMBNAILING_FAILED);
253 REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID);
254 REGISTER_ATTRIBUTE (PREVIEW_ICON);
255 REGISTER_ATTRIBUTE (FILESYSTEM_SIZE);
256 REGISTER_ATTRIBUTE (FILESYSTEM_FREE);
257 REGISTER_ATTRIBUTE (FILESYSTEM_TYPE);
258 REGISTER_ATTRIBUTE (FILESYSTEM_READONLY);
259 REGISTER_ATTRIBUTE (FILESYSTEM_USE_PREVIEW);
260 REGISTER_ATTRIBUTE (GVFS_BACKEND);
261 REGISTER_ATTRIBUTE (SELINUX_CONTEXT);
262 REGISTER_ATTRIBUTE (TRASH_ITEM_COUNT);
263 REGISTER_ATTRIBUTE (TRASH_ORIG_PATH);
264 REGISTER_ATTRIBUTE (TRASH_DELETION_DATE);
266 #undef REGISTER_ATTRIBUTE
269 static guint32
270 lookup_namespace (const char *namespace)
272 NSInfo *ns_info;
273 guint32 id;
275 G_LOCK (attribute_hash);
277 ensure_attribute_hash ();
279 ns_info = _lookup_namespace (namespace);
280 id = 0;
281 if (ns_info)
282 id = ns_info->id;
284 G_UNLOCK (attribute_hash);
286 return id;
289 static char *
290 get_attribute_for_id (int attribute)
292 char *s;
293 G_LOCK (attribute_hash);
294 s = attributes[GET_NS(attribute)][GET_ID(attribute)];
295 G_UNLOCK (attribute_hash);
296 return s;
299 static guint32
300 lookup_attribute (const char *attribute)
302 guint32 attr_id;
304 G_LOCK (attribute_hash);
305 ensure_attribute_hash ();
307 attr_id = _lookup_attribute (attribute);
309 G_UNLOCK (attribute_hash);
311 return attr_id;
314 static void
315 g_file_info_finalize (GObject *object)
317 GFileInfo *info;
318 int i;
319 GFileAttribute *attrs;
321 info = G_FILE_INFO (object);
323 attrs = (GFileAttribute *)info->attributes->data;
324 for (i = 0; i < info->attributes->len; i++)
325 _g_file_attribute_value_clear (&attrs[i].value);
326 g_array_free (info->attributes, TRUE);
328 if (info->mask != NO_ATTRIBUTE_MASK)
329 g_file_attribute_matcher_unref (info->mask);
331 G_OBJECT_CLASS (g_file_info_parent_class)->finalize (object);
334 static void
335 g_file_info_class_init (GFileInfoClass *klass)
337 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
339 gobject_class->finalize = g_file_info_finalize;
342 static void
343 g_file_info_init (GFileInfo *info)
345 info->mask = NO_ATTRIBUTE_MASK;
346 info->attributes = g_array_new (FALSE, FALSE,
347 sizeof (GFileAttribute));
351 * g_file_info_new:
353 * Creates a new file info structure.
355 * Returns: a #GFileInfo.
357 GFileInfo *
358 g_file_info_new (void)
360 return g_object_new (G_TYPE_FILE_INFO, NULL);
364 * g_file_info_copy_into:
365 * @src_info: source to copy attributes from.
366 * @dest_info: destination to copy attributes to.
368 * First clears all of the [GFileAttribute][gio-GFileAttribute] of @dest_info,
369 * and then copies all of the file attributes from @src_info to @dest_info.
371 void
372 g_file_info_copy_into (GFileInfo *src_info,
373 GFileInfo *dest_info)
375 GFileAttribute *source, *dest;
376 int i;
378 g_return_if_fail (G_IS_FILE_INFO (src_info));
379 g_return_if_fail (G_IS_FILE_INFO (dest_info));
381 dest = (GFileAttribute *)dest_info->attributes->data;
382 for (i = 0; i < dest_info->attributes->len; i++)
383 _g_file_attribute_value_clear (&dest[i].value);
385 g_array_set_size (dest_info->attributes,
386 src_info->attributes->len);
388 source = (GFileAttribute *)src_info->attributes->data;
389 dest = (GFileAttribute *)dest_info->attributes->data;
391 for (i = 0; i < src_info->attributes->len; i++)
393 dest[i].attribute = source[i].attribute;
394 dest[i].value.type = G_FILE_ATTRIBUTE_TYPE_INVALID;
395 _g_file_attribute_value_set (&dest[i].value, &source[i].value);
398 if (dest_info->mask != NO_ATTRIBUTE_MASK)
399 g_file_attribute_matcher_unref (dest_info->mask);
401 if (src_info->mask == NO_ATTRIBUTE_MASK)
402 dest_info->mask = NO_ATTRIBUTE_MASK;
403 else
404 dest_info->mask = g_file_attribute_matcher_ref (src_info->mask);
408 * g_file_info_dup:
409 * @other: a #GFileInfo.
411 * Duplicates a file info structure.
413 * Returns: (transfer full): a duplicate #GFileInfo of @other.
415 GFileInfo *
416 g_file_info_dup (GFileInfo *other)
418 GFileInfo *new;
420 g_return_val_if_fail (G_IS_FILE_INFO (other), NULL);
422 new = g_file_info_new ();
423 g_file_info_copy_into (other, new);
424 return new;
428 * g_file_info_set_attribute_mask:
429 * @info: a #GFileInfo.
430 * @mask: a #GFileAttributeMatcher.
432 * Sets @mask on @info to match specific attribute types.
434 void
435 g_file_info_set_attribute_mask (GFileInfo *info,
436 GFileAttributeMatcher *mask)
438 GFileAttribute *attr;
439 int i;
441 g_return_if_fail (G_IS_FILE_INFO (info));
443 if (mask != info->mask)
445 if (info->mask != NO_ATTRIBUTE_MASK)
446 g_file_attribute_matcher_unref (info->mask);
447 info->mask = g_file_attribute_matcher_ref (mask);
449 /* Remove non-matching attributes */
450 for (i = 0; i < info->attributes->len; i++)
452 attr = &g_array_index (info->attributes, GFileAttribute, i);
453 if (!_g_file_attribute_matcher_matches_id (mask,
454 attr->attribute))
456 _g_file_attribute_value_clear (&attr->value);
457 g_array_remove_index (info->attributes, i);
458 i--;
465 * g_file_info_unset_attribute_mask:
466 * @info: #GFileInfo.
468 * Unsets a mask set by g_file_info_set_attribute_mask(), if one
469 * is set.
471 void
472 g_file_info_unset_attribute_mask (GFileInfo *info)
474 g_return_if_fail (G_IS_FILE_INFO (info));
476 if (info->mask != NO_ATTRIBUTE_MASK)
477 g_file_attribute_matcher_unref (info->mask);
478 info->mask = NO_ATTRIBUTE_MASK;
482 * g_file_info_clear_status:
483 * @info: a #GFileInfo.
485 * Clears the status information from @info.
487 void
488 g_file_info_clear_status (GFileInfo *info)
490 GFileAttribute *attrs;
491 int i;
493 g_return_if_fail (G_IS_FILE_INFO (info));
495 attrs = (GFileAttribute *)info->attributes->data;
496 for (i = 0; i < info->attributes->len; i++)
497 attrs[i].value.status = G_FILE_ATTRIBUTE_STATUS_UNSET;
500 static int
501 g_file_info_find_place (GFileInfo *info,
502 guint32 attribute)
504 int min, max, med;
505 GFileAttribute *attrs;
506 /* Binary search for the place where attribute would be, if it's
507 in the array */
509 min = 0;
510 max = info->attributes->len;
512 attrs = (GFileAttribute *)info->attributes->data;
514 while (min < max)
516 med = min + (max - min) / 2;
517 if (attrs[med].attribute == attribute)
519 min = med;
520 break;
522 else if (attrs[med].attribute < attribute)
523 min = med + 1;
524 else /* attrs[med].attribute > attribute */
525 max = med;
528 return min;
531 static GFileAttributeValue *
532 g_file_info_find_value (GFileInfo *info,
533 guint32 attr_id)
535 GFileAttribute *attrs;
536 int i;
538 i = g_file_info_find_place (info, attr_id);
539 attrs = (GFileAttribute *)info->attributes->data;
540 if (i < info->attributes->len &&
541 attrs[i].attribute == attr_id)
542 return &attrs[i].value;
544 return NULL;
547 static GFileAttributeValue *
548 g_file_info_find_value_by_name (GFileInfo *info,
549 const char *attribute)
551 guint32 attr_id;
553 attr_id = lookup_attribute (attribute);
554 return g_file_info_find_value (info, attr_id);
558 * g_file_info_has_attribute:
559 * @info: a #GFileInfo.
560 * @attribute: a file attribute key.
562 * Checks if a file info structure has an attribute named @attribute.
564 * Returns: %TRUE if @Ginfo has an attribute named @attribute,
565 * %FALSE otherwise.
567 gboolean
568 g_file_info_has_attribute (GFileInfo *info,
569 const char *attribute)
571 GFileAttributeValue *value;
573 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
574 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
576 value = g_file_info_find_value_by_name (info, attribute);
577 return value != NULL;
581 * g_file_info_has_namespace:
582 * @info: a #GFileInfo.
583 * @name_space: a file attribute namespace.
585 * Checks if a file info structure has an attribute in the
586 * specified @name_space.
588 * Returns: %TRUE if @Ginfo has an attribute in @name_space,
589 * %FALSE otherwise.
591 * Since: 2.22
593 gboolean
594 g_file_info_has_namespace (GFileInfo *info,
595 const char *name_space)
597 GFileAttribute *attrs;
598 guint32 ns_id;
599 int i;
601 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
602 g_return_val_if_fail (name_space != NULL, FALSE);
604 ns_id = lookup_namespace (name_space);
606 attrs = (GFileAttribute *)info->attributes->data;
607 for (i = 0; i < info->attributes->len; i++)
609 if (GET_NS (attrs[i].attribute) == ns_id)
610 return TRUE;
613 return FALSE;
617 * g_file_info_list_attributes:
618 * @info: a #GFileInfo.
619 * @name_space: (nullable): a file attribute key's namespace, or %NULL to list
620 * all attributes.
622 * Lists the file info structure's attributes.
624 * Returns: (nullable) (array zero-terminated=1) (transfer full): a
625 * null-terminated array of strings of all of the possible attribute
626 * types for the given @name_space, or %NULL on error.
628 char **
629 g_file_info_list_attributes (GFileInfo *info,
630 const char *name_space)
632 GPtrArray *names;
633 GFileAttribute *attrs;
634 guint32 attribute;
635 guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0;
636 int i;
638 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
640 names = g_ptr_array_new ();
641 attrs = (GFileAttribute *)info->attributes->data;
642 for (i = 0; i < info->attributes->len; i++)
644 attribute = attrs[i].attribute;
645 if (ns_id == 0 || GET_NS (attribute) == ns_id)
646 g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute)));
649 /* NULL terminate */
650 g_ptr_array_add (names, NULL);
652 return (char **)g_ptr_array_free (names, FALSE);
656 * g_file_info_get_attribute_type:
657 * @info: a #GFileInfo.
658 * @attribute: a file attribute key.
660 * Gets the attribute type for an attribute key.
662 * Returns: a #GFileAttributeType for the given @attribute, or
663 * %G_FILE_ATTRIBUTE_TYPE_INVALID if the key is not set.
665 GFileAttributeType
666 g_file_info_get_attribute_type (GFileInfo *info,
667 const char *attribute)
669 GFileAttributeValue *value;
671 g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_ATTRIBUTE_TYPE_INVALID);
672 g_return_val_if_fail (attribute != NULL && *attribute != '\0', G_FILE_ATTRIBUTE_TYPE_INVALID);
674 value = g_file_info_find_value_by_name (info, attribute);
675 if (value)
676 return value->type;
677 else
678 return G_FILE_ATTRIBUTE_TYPE_INVALID;
682 * g_file_info_remove_attribute:
683 * @info: a #GFileInfo.
684 * @attribute: a file attribute key.
686 * Removes all cases of @attribute from @info if it exists.
688 void
689 g_file_info_remove_attribute (GFileInfo *info,
690 const char *attribute)
692 guint32 attr_id;
693 GFileAttribute *attrs;
694 int i;
696 g_return_if_fail (G_IS_FILE_INFO (info));
697 g_return_if_fail (attribute != NULL && *attribute != '\0');
699 attr_id = lookup_attribute (attribute);
701 i = g_file_info_find_place (info, attr_id);
702 attrs = (GFileAttribute *)info->attributes->data;
703 if (i < info->attributes->len &&
704 attrs[i].attribute == attr_id)
706 _g_file_attribute_value_clear (&attrs[i].value);
707 g_array_remove_index (info->attributes, i);
712 * g_file_info_get_attribute_data:
713 * @info: a #GFileInfo
714 * @attribute: a file attribute key
715 * @type: (out) (optional): return location for the attribute type, or %NULL
716 * @value_pp: (out) (optional) (not nullable): return location for the
717 * attribute value, or %NULL; the attribute value will not be %NULL
718 * @status: (out) (optional): return location for the attribute status, or %NULL
720 * Gets the attribute type, value and status for an attribute key.
722 * Returns: (transfer none): %TRUE if @info has an attribute named @attribute,
723 * %FALSE otherwise.
725 gboolean
726 g_file_info_get_attribute_data (GFileInfo *info,
727 const char *attribute,
728 GFileAttributeType *type,
729 gpointer *value_pp,
730 GFileAttributeStatus *status)
732 GFileAttributeValue *value;
734 value = g_file_info_find_value_by_name (info, attribute);
735 if (value == NULL)
736 return FALSE;
738 if (status)
739 *status = value->status;
741 if (type)
742 *type = value->type;
744 if (value_pp)
745 *value_pp = _g_file_attribute_value_peek_as_pointer (value);
747 return TRUE;
751 * g_file_info_get_attribute_status:
752 * @info: a #GFileInfo
753 * @attribute: a file attribute key
755 * Gets the attribute status for an attribute key.
757 * Returns: a #GFileAttributeStatus for the given @attribute, or
758 * %G_FILE_ATTRIBUTE_STATUS_UNSET if the key is invalid.
761 GFileAttributeStatus
762 g_file_info_get_attribute_status (GFileInfo *info,
763 const char *attribute)
765 GFileAttributeValue *val;
767 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
768 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
770 val = g_file_info_find_value_by_name (info, attribute);
771 if (val)
772 return val->status;
774 return G_FILE_ATTRIBUTE_STATUS_UNSET;
778 * g_file_info_set_attribute_status:
779 * @info: a #GFileInfo
780 * @attribute: a file attribute key
781 * @status: a #GFileAttributeStatus
783 * Sets the attribute status for an attribute key. This is only
784 * needed by external code that implement g_file_set_attributes_from_info()
785 * or similar functions.
787 * The attribute must exist in @info for this to work. Otherwise %FALSE
788 * is returned and @info is unchanged.
790 * Returns: %TRUE if the status was changed, %FALSE if the key was not set.
792 * Since: 2.22
794 gboolean
795 g_file_info_set_attribute_status (GFileInfo *info,
796 const char *attribute,
797 GFileAttributeStatus status)
799 GFileAttributeValue *val;
801 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
802 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
804 val = g_file_info_find_value_by_name (info, attribute);
805 if (val)
807 val->status = status;
808 return TRUE;
811 return FALSE;
814 GFileAttributeValue *
815 _g_file_info_get_attribute_value (GFileInfo *info,
816 const char *attribute)
819 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
820 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
822 return g_file_info_find_value_by_name (info, attribute);
826 * g_file_info_get_attribute_as_string:
827 * @info: a #GFileInfo.
828 * @attribute: a file attribute key.
830 * Gets the value of a attribute, formated as a string.
831 * This escapes things as needed to make the string valid
832 * utf8.
834 * Returns: a UTF-8 string associated with the given @attribute.
835 * When you're done with the string it must be freed with g_free().
837 char *
838 g_file_info_get_attribute_as_string (GFileInfo *info,
839 const char *attribute)
841 GFileAttributeValue *val;
842 val = _g_file_info_get_attribute_value (info, attribute);
843 if (val)
844 return _g_file_attribute_value_as_string (val);
845 return NULL;
850 * g_file_info_get_attribute_object:
851 * @info: a #GFileInfo.
852 * @attribute: a file attribute key.
854 * Gets the value of a #GObject attribute. If the attribute does
855 * not contain a #GObject, %NULL will be returned.
857 * Returns: (transfer none): a #GObject associated with the given @attribute, or
858 * %NULL otherwise.
860 GObject *
861 g_file_info_get_attribute_object (GFileInfo *info,
862 const char *attribute)
864 GFileAttributeValue *value;
866 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
867 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
869 value = g_file_info_find_value_by_name (info, attribute);
870 return _g_file_attribute_value_get_object (value);
874 * g_file_info_get_attribute_string:
875 * @info: a #GFileInfo.
876 * @attribute: a file attribute key.
878 * Gets the value of a string attribute. If the attribute does
879 * not contain a string, %NULL will be returned.
881 * Returns: the contents of the @attribute value as a UTF-8 string, or
882 * %NULL otherwise.
884 const char *
885 g_file_info_get_attribute_string (GFileInfo *info,
886 const char *attribute)
888 GFileAttributeValue *value;
890 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
891 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
893 value = g_file_info_find_value_by_name (info, attribute);
894 return _g_file_attribute_value_get_string (value);
898 * g_file_info_get_attribute_byte_string:
899 * @info: a #GFileInfo.
900 * @attribute: a file attribute key.
902 * Gets the value of a byte string attribute. If the attribute does
903 * not contain a byte string, %NULL will be returned.
905 * Returns: the contents of the @attribute value as a byte string, or
906 * %NULL otherwise.
908 const char *
909 g_file_info_get_attribute_byte_string (GFileInfo *info,
910 const char *attribute)
912 GFileAttributeValue *value;
914 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
915 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
917 value = g_file_info_find_value_by_name (info, attribute);
918 return _g_file_attribute_value_get_byte_string (value);
922 * g_file_info_get_attribute_stringv:
923 * @info: a #GFileInfo.
924 * @attribute: a file attribute key.
926 * Gets the value of a stringv attribute. If the attribute does
927 * not contain a stringv, %NULL will be returned.
929 * Returns: (transfer none): the contents of the @attribute value as a stringv, or
930 * %NULL otherwise. Do not free. These returned strings are UTF-8.
932 * Since: 2.22
934 char **
935 g_file_info_get_attribute_stringv (GFileInfo *info,
936 const char *attribute)
938 GFileAttributeValue *value;
940 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
941 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
943 value = g_file_info_find_value_by_name (info, attribute);
944 return _g_file_attribute_value_get_stringv (value);
948 * g_file_info_get_attribute_boolean:
949 * @info: a #GFileInfo.
950 * @attribute: a file attribute key.
952 * Gets the value of a boolean attribute. If the attribute does not
953 * contain a boolean value, %FALSE will be returned.
955 * Returns: the boolean value contained within the attribute.
957 gboolean
958 g_file_info_get_attribute_boolean (GFileInfo *info,
959 const char *attribute)
961 GFileAttributeValue *value;
963 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
964 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
966 value = g_file_info_find_value_by_name (info, attribute);
967 return _g_file_attribute_value_get_boolean (value);
971 * g_file_info_get_attribute_uint32:
972 * @info: a #GFileInfo.
973 * @attribute: a file attribute key.
975 * Gets an unsigned 32-bit integer contained within the attribute. If the
976 * attribute does not contain an unsigned 32-bit integer, or is invalid,
977 * 0 will be returned.
979 * Returns: an unsigned 32-bit integer from the attribute.
981 guint32
982 g_file_info_get_attribute_uint32 (GFileInfo *info,
983 const char *attribute)
985 GFileAttributeValue *value;
987 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
988 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
990 value = g_file_info_find_value_by_name (info, attribute);
991 return _g_file_attribute_value_get_uint32 (value);
995 * g_file_info_get_attribute_int32:
996 * @info: a #GFileInfo.
997 * @attribute: a file attribute key.
999 * Gets a signed 32-bit integer contained within the attribute. If the
1000 * attribute does not contain a signed 32-bit integer, or is invalid,
1001 * 0 will be returned.
1003 * Returns: a signed 32-bit integer from the attribute.
1005 gint32
1006 g_file_info_get_attribute_int32 (GFileInfo *info,
1007 const char *attribute)
1009 GFileAttributeValue *value;
1011 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1012 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1014 value = g_file_info_find_value_by_name (info, attribute);
1015 return _g_file_attribute_value_get_int32 (value);
1019 * g_file_info_get_attribute_uint64:
1020 * @info: a #GFileInfo.
1021 * @attribute: a file attribute key.
1023 * Gets a unsigned 64-bit integer contained within the attribute. If the
1024 * attribute does not contain an unsigned 64-bit integer, or is invalid,
1025 * 0 will be returned.
1027 * Returns: a unsigned 64-bit integer from the attribute.
1029 guint64
1030 g_file_info_get_attribute_uint64 (GFileInfo *info,
1031 const char *attribute)
1033 GFileAttributeValue *value;
1035 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1036 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1038 value = g_file_info_find_value_by_name (info, attribute);
1039 return _g_file_attribute_value_get_uint64 (value);
1043 * g_file_info_get_attribute_int64:
1044 * @info: a #GFileInfo.
1045 * @attribute: a file attribute key.
1047 * Gets a signed 64-bit integer contained within the attribute. If the
1048 * attribute does not contain an signed 64-bit integer, or is invalid,
1049 * 0 will be returned.
1051 * Returns: a signed 64-bit integer from the attribute.
1053 gint64
1054 g_file_info_get_attribute_int64 (GFileInfo *info,
1055 const char *attribute)
1057 GFileAttributeValue *value;
1059 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1060 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1062 value = g_file_info_find_value_by_name (info, attribute);
1063 return _g_file_attribute_value_get_int64 (value);
1066 static GFileAttributeValue *
1067 g_file_info_create_value (GFileInfo *info,
1068 guint32 attr_id)
1070 GFileAttribute *attrs;
1071 int i;
1073 if (info->mask != NO_ATTRIBUTE_MASK &&
1074 !_g_file_attribute_matcher_matches_id (info->mask, attr_id))
1075 return NULL;
1077 i = g_file_info_find_place (info, attr_id);
1079 attrs = (GFileAttribute *)info->attributes->data;
1080 if (i < info->attributes->len &&
1081 attrs[i].attribute == attr_id)
1082 return &attrs[i].value;
1083 else
1085 GFileAttribute attr = { 0 };
1086 attr.attribute = attr_id;
1087 g_array_insert_val (info->attributes, i, attr);
1089 attrs = (GFileAttribute *)info->attributes->data;
1090 return &attrs[i].value;
1094 void
1095 _g_file_info_set_attribute_by_id (GFileInfo *info,
1096 guint32 attribute,
1097 GFileAttributeType type,
1098 gpointer value_p)
1100 GFileAttributeValue *value;
1102 value = g_file_info_create_value (info, attribute);
1104 if (value)
1105 _g_file_attribute_value_set_from_pointer (value, type, value_p, TRUE);
1109 * g_file_info_set_attribute:
1110 * @info: a #GFileInfo.
1111 * @attribute: a file attribute key.
1112 * @type: a #GFileAttributeType
1113 * @value_p: (not nullable): pointer to the value
1115 * Sets the @attribute to contain the given value, if possible. To unset the
1116 * attribute, use %G_FILE_ATTRIBUTE_TYPE_INVALID for @type.
1118 void
1119 g_file_info_set_attribute (GFileInfo *info,
1120 const char *attribute,
1121 GFileAttributeType type,
1122 gpointer value_p)
1124 g_return_if_fail (G_IS_FILE_INFO (info));
1125 g_return_if_fail (attribute != NULL && *attribute != '\0');
1127 _g_file_info_set_attribute_by_id (info, lookup_attribute (attribute), type, value_p);
1130 void
1131 _g_file_info_set_attribute_object_by_id (GFileInfo *info,
1132 guint32 attribute,
1133 GObject *attr_value)
1135 GFileAttributeValue *value;
1137 value = g_file_info_create_value (info, attribute);
1138 if (value)
1139 _g_file_attribute_value_set_object (value, attr_value);
1143 * g_file_info_set_attribute_object:
1144 * @info: a #GFileInfo.
1145 * @attribute: a file attribute key.
1146 * @attr_value: a #GObject.
1148 * Sets the @attribute to contain the given @attr_value,
1149 * if possible.
1151 void
1152 g_file_info_set_attribute_object (GFileInfo *info,
1153 const char *attribute,
1154 GObject *attr_value)
1156 g_return_if_fail (G_IS_FILE_INFO (info));
1157 g_return_if_fail (attribute != NULL && *attribute != '\0');
1158 g_return_if_fail (G_IS_OBJECT (attr_value));
1160 _g_file_info_set_attribute_object_by_id (info,
1161 lookup_attribute (attribute),
1162 attr_value);
1165 void
1166 _g_file_info_set_attribute_stringv_by_id (GFileInfo *info,
1167 guint32 attribute,
1168 char **attr_value)
1170 GFileAttributeValue *value;
1172 value = g_file_info_create_value (info, attribute);
1173 if (value)
1174 _g_file_attribute_value_set_stringv (value, attr_value);
1178 * g_file_info_set_attribute_stringv:
1179 * @info: a #GFileInfo.
1180 * @attribute: a file attribute key
1181 * @attr_value: (array) (element-type utf8): a %NULL terminated array of UTF-8 strings.
1183 * Sets the @attribute to contain the given @attr_value,
1184 * if possible.
1186 * Sinze: 2.22
1188 void
1189 g_file_info_set_attribute_stringv (GFileInfo *info,
1190 const char *attribute,
1191 char **attr_value)
1193 g_return_if_fail (G_IS_FILE_INFO (info));
1194 g_return_if_fail (attribute != NULL && *attribute != '\0');
1195 g_return_if_fail (attr_value != NULL);
1197 _g_file_info_set_attribute_stringv_by_id (info,
1198 lookup_attribute (attribute),
1199 attr_value);
1202 void
1203 _g_file_info_set_attribute_string_by_id (GFileInfo *info,
1204 guint32 attribute,
1205 const char *attr_value)
1207 GFileAttributeValue *value;
1209 value = g_file_info_create_value (info, attribute);
1210 if (value)
1211 _g_file_attribute_value_set_string (value, attr_value);
1215 * g_file_info_set_attribute_string:
1216 * @info: a #GFileInfo.
1217 * @attribute: a file attribute key.
1218 * @attr_value: a UTF-8 string.
1220 * Sets the @attribute to contain the given @attr_value,
1221 * if possible.
1223 void
1224 g_file_info_set_attribute_string (GFileInfo *info,
1225 const char *attribute,
1226 const char *attr_value)
1228 g_return_if_fail (G_IS_FILE_INFO (info));
1229 g_return_if_fail (attribute != NULL && *attribute != '\0');
1230 g_return_if_fail (attr_value != NULL);
1232 _g_file_info_set_attribute_string_by_id (info,
1233 lookup_attribute (attribute),
1234 attr_value);
1237 void
1238 _g_file_info_set_attribute_byte_string_by_id (GFileInfo *info,
1239 guint32 attribute,
1240 const char *attr_value)
1242 GFileAttributeValue *value;
1244 value = g_file_info_create_value (info, attribute);
1245 if (value)
1246 _g_file_attribute_value_set_byte_string (value, attr_value);
1250 * g_file_info_set_attribute_byte_string:
1251 * @info: a #GFileInfo.
1252 * @attribute: a file attribute key.
1253 * @attr_value: a byte string.
1255 * Sets the @attribute to contain the given @attr_value,
1256 * if possible.
1258 void
1259 g_file_info_set_attribute_byte_string (GFileInfo *info,
1260 const char *attribute,
1261 const char *attr_value)
1263 g_return_if_fail (G_IS_FILE_INFO (info));
1264 g_return_if_fail (attribute != NULL && *attribute != '\0');
1265 g_return_if_fail (attr_value != NULL);
1267 _g_file_info_set_attribute_byte_string_by_id (info,
1268 lookup_attribute (attribute),
1269 attr_value);
1272 void
1273 _g_file_info_set_attribute_boolean_by_id (GFileInfo *info,
1274 guint32 attribute,
1275 gboolean attr_value)
1277 GFileAttributeValue *value;
1279 value = g_file_info_create_value (info, attribute);
1280 if (value)
1281 _g_file_attribute_value_set_boolean (value, attr_value);
1285 * g_file_info_set_attribute_boolean:
1286 * @info: a #GFileInfo.
1287 * @attribute: a file attribute key.
1288 * @attr_value: a boolean value.
1290 * Sets the @attribute to contain the given @attr_value,
1291 * if possible.
1293 void
1294 g_file_info_set_attribute_boolean (GFileInfo *info,
1295 const char *attribute,
1296 gboolean attr_value)
1298 g_return_if_fail (G_IS_FILE_INFO (info));
1299 g_return_if_fail (attribute != NULL && *attribute != '\0');
1301 _g_file_info_set_attribute_boolean_by_id (info,
1302 lookup_attribute (attribute),
1303 attr_value);
1306 void
1307 _g_file_info_set_attribute_uint32_by_id (GFileInfo *info,
1308 guint32 attribute,
1309 guint32 attr_value)
1311 GFileAttributeValue *value;
1313 value = g_file_info_create_value (info, attribute);
1314 if (value)
1315 _g_file_attribute_value_set_uint32 (value, attr_value);
1319 * g_file_info_set_attribute_uint32:
1320 * @info: a #GFileInfo.
1321 * @attribute: a file attribute key.
1322 * @attr_value: an unsigned 32-bit integer.
1324 * Sets the @attribute to contain the given @attr_value,
1325 * if possible.
1327 void
1328 g_file_info_set_attribute_uint32 (GFileInfo *info,
1329 const char *attribute,
1330 guint32 attr_value)
1332 g_return_if_fail (G_IS_FILE_INFO (info));
1333 g_return_if_fail (attribute != NULL && *attribute != '\0');
1335 _g_file_info_set_attribute_uint32_by_id (info,
1336 lookup_attribute (attribute),
1337 attr_value);
1340 void
1341 _g_file_info_set_attribute_int32_by_id (GFileInfo *info,
1342 guint32 attribute,
1343 gint32 attr_value)
1345 GFileAttributeValue *value;
1347 value = g_file_info_create_value (info, attribute);
1348 if (value)
1349 _g_file_attribute_value_set_int32 (value, attr_value);
1353 * g_file_info_set_attribute_int32:
1354 * @info: a #GFileInfo.
1355 * @attribute: a file attribute key.
1356 * @attr_value: a signed 32-bit integer
1358 * Sets the @attribute to contain the given @attr_value,
1359 * if possible.
1361 void
1362 g_file_info_set_attribute_int32 (GFileInfo *info,
1363 const char *attribute,
1364 gint32 attr_value)
1366 g_return_if_fail (G_IS_FILE_INFO (info));
1367 g_return_if_fail (attribute != NULL && *attribute != '\0');
1369 _g_file_info_set_attribute_int32_by_id (info,
1370 lookup_attribute (attribute),
1371 attr_value);
1374 void
1375 _g_file_info_set_attribute_uint64_by_id (GFileInfo *info,
1376 guint32 attribute,
1377 guint64 attr_value)
1379 GFileAttributeValue *value;
1381 value = g_file_info_create_value (info, attribute);
1382 if (value)
1383 _g_file_attribute_value_set_uint64 (value, attr_value);
1387 * g_file_info_set_attribute_uint64:
1388 * @info: a #GFileInfo.
1389 * @attribute: a file attribute key.
1390 * @attr_value: an unsigned 64-bit integer.
1392 * Sets the @attribute to contain the given @attr_value,
1393 * if possible.
1395 void
1396 g_file_info_set_attribute_uint64 (GFileInfo *info,
1397 const char *attribute,
1398 guint64 attr_value)
1400 g_return_if_fail (G_IS_FILE_INFO (info));
1401 g_return_if_fail (attribute != NULL && *attribute != '\0');
1403 _g_file_info_set_attribute_uint64_by_id (info,
1404 lookup_attribute (attribute),
1405 attr_value);
1408 void
1409 _g_file_info_set_attribute_int64_by_id (GFileInfo *info,
1410 guint32 attribute,
1411 gint64 attr_value)
1413 GFileAttributeValue *value;
1415 value = g_file_info_create_value (info, attribute);
1416 if (value)
1417 _g_file_attribute_value_set_int64 (value, attr_value);
1421 * g_file_info_set_attribute_int64:
1422 * @info: a #GFileInfo.
1423 * @attribute: attribute name to set.
1424 * @attr_value: int64 value to set attribute to.
1426 * Sets the @attribute to contain the given @attr_value,
1427 * if possible.
1430 void
1431 g_file_info_set_attribute_int64 (GFileInfo *info,
1432 const char *attribute,
1433 gint64 attr_value)
1435 g_return_if_fail (G_IS_FILE_INFO (info));
1436 g_return_if_fail (attribute != NULL && *attribute != '\0');
1438 _g_file_info_set_attribute_int64_by_id (info,
1439 lookup_attribute (attribute),
1440 attr_value);
1443 /* Helper getters */
1445 * g_file_info_get_deletion_date:
1446 * @info: a #GFileInfo.
1448 * Returns the #GDateTime representing the deletion date of the file, as
1449 * available in G_FILE_ATTRIBUTE_TRASH_DELETION_DATE. If the
1450 * G_FILE_ATTRIBUTE_TRASH_DELETION_DATE attribute is unset, %NULL is returned.
1452 * Returns: a #GDateTime, or %NULL.
1454 * Since: 2.36
1456 GDateTime *
1457 g_file_info_get_deletion_date (GFileInfo *info)
1459 static guint32 attr = 0;
1460 GFileAttributeValue *value;
1461 const char *date_str;
1462 GTimeVal tv;
1464 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1466 if (attr == 0)
1467 attr = lookup_attribute (G_FILE_ATTRIBUTE_TRASH_DELETION_DATE);
1469 value = g_file_info_find_value (info, attr);
1470 date_str = _g_file_attribute_value_get_string (value);
1471 if (!date_str)
1472 return NULL;
1474 if (g_time_val_from_iso8601 (date_str, &tv) == FALSE)
1475 return NULL;
1477 return g_date_time_new_from_timeval_local (&tv);
1481 * g_file_info_get_file_type:
1482 * @info: a #GFileInfo.
1484 * Gets a file's type (whether it is a regular file, symlink, etc).
1485 * This is different from the file's content type, see g_file_info_get_content_type().
1487 * Returns: a #GFileType for the given file.
1489 GFileType
1490 g_file_info_get_file_type (GFileInfo *info)
1492 static guint32 attr = 0;
1493 GFileAttributeValue *value;
1495 g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_TYPE_UNKNOWN);
1497 if (attr == 0)
1498 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
1500 value = g_file_info_find_value (info, attr);
1501 return (GFileType)_g_file_attribute_value_get_uint32 (value);
1505 * g_file_info_get_is_hidden:
1506 * @info: a #GFileInfo.
1508 * Checks if a file is hidden.
1510 * Returns: %TRUE if the file is a hidden file, %FALSE otherwise.
1512 gboolean
1513 g_file_info_get_is_hidden (GFileInfo *info)
1515 static guint32 attr = 0;
1516 GFileAttributeValue *value;
1518 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1520 if (attr == 0)
1521 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
1523 value = g_file_info_find_value (info, attr);
1524 return (GFileType)_g_file_attribute_value_get_boolean (value);
1528 * g_file_info_get_is_backup:
1529 * @info: a #GFileInfo.
1531 * Checks if a file is a backup file.
1533 * Returns: %TRUE if file is a backup file, %FALSE otherwise.
1535 gboolean
1536 g_file_info_get_is_backup (GFileInfo *info)
1538 static guint32 attr = 0;
1539 GFileAttributeValue *value;
1541 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1543 if (attr == 0)
1544 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP);
1546 value = g_file_info_find_value (info, attr);
1547 return (GFileType)_g_file_attribute_value_get_boolean (value);
1551 * g_file_info_get_is_symlink:
1552 * @info: a #GFileInfo.
1554 * Checks if a file is a symlink.
1556 * Returns: %TRUE if the given @info is a symlink.
1558 gboolean
1559 g_file_info_get_is_symlink (GFileInfo *info)
1561 static guint32 attr = 0;
1562 GFileAttributeValue *value;
1564 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1566 if (attr == 0)
1567 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
1569 value = g_file_info_find_value (info, attr);
1570 return (GFileType)_g_file_attribute_value_get_boolean (value);
1574 * g_file_info_get_name:
1575 * @info: a #GFileInfo.
1577 * Gets the name for a file.
1579 * Returns: (type filename): a string containing the file name.
1581 const char *
1582 g_file_info_get_name (GFileInfo *info)
1584 static guint32 attr = 0;
1585 GFileAttributeValue *value;
1587 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1589 if (attr == 0)
1590 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
1592 value = g_file_info_find_value (info, attr);
1593 return _g_file_attribute_value_get_byte_string (value);
1597 * g_file_info_get_display_name:
1598 * @info: a #GFileInfo.
1600 * Gets a display name for a file.
1602 * Returns: a string containing the display name.
1604 const char *
1605 g_file_info_get_display_name (GFileInfo *info)
1607 static guint32 attr = 0;
1608 GFileAttributeValue *value;
1610 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1612 if (attr == 0)
1613 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
1615 value = g_file_info_find_value (info, attr);
1616 return _g_file_attribute_value_get_string (value);
1620 * g_file_info_get_edit_name:
1621 * @info: a #GFileInfo.
1623 * Gets the edit name for a file.
1625 * Returns: a string containing the edit name.
1627 const char *
1628 g_file_info_get_edit_name (GFileInfo *info)
1630 static guint32 attr = 0;
1631 GFileAttributeValue *value;
1633 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1635 if (attr == 0)
1636 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
1638 value = g_file_info_find_value (info, attr);
1639 return _g_file_attribute_value_get_string (value);
1643 * g_file_info_get_icon:
1644 * @info: a #GFileInfo.
1646 * Gets the icon for a file.
1648 * Returns: (transfer none): #GIcon for the given @info.
1650 GIcon *
1651 g_file_info_get_icon (GFileInfo *info)
1653 static guint32 attr = 0;
1654 GFileAttributeValue *value;
1655 GObject *obj;
1657 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1659 if (attr == 0)
1660 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
1662 value = g_file_info_find_value (info, attr);
1663 obj = _g_file_attribute_value_get_object (value);
1664 if (G_IS_ICON (obj))
1665 return G_ICON (obj);
1666 return NULL;
1670 * g_file_info_get_symbolic_icon:
1671 * @info: a #GFileInfo.
1673 * Gets the symbolic icon for a file.
1675 * Returns: (transfer none): #GIcon for the given @info.
1677 * Since: 2.34
1679 GIcon *
1680 g_file_info_get_symbolic_icon (GFileInfo *info)
1682 static guint32 attr = 0;
1683 GFileAttributeValue *value;
1684 GObject *obj;
1686 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1688 if (attr == 0)
1689 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON);
1691 value = g_file_info_find_value (info, attr);
1692 obj = _g_file_attribute_value_get_object (value);
1693 if (G_IS_ICON (obj))
1694 return G_ICON (obj);
1695 return NULL;
1699 * g_file_info_get_content_type:
1700 * @info: a #GFileInfo.
1702 * Gets the file's content type.
1704 * Returns: a string containing the file's content type.
1706 const char *
1707 g_file_info_get_content_type (GFileInfo *info)
1709 static guint32 attr = 0;
1710 GFileAttributeValue *value;
1712 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1714 if (attr == 0)
1715 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1717 value = g_file_info_find_value (info, attr);
1718 return _g_file_attribute_value_get_string (value);
1722 * g_file_info_get_size:
1723 * @info: a #GFileInfo.
1725 * Gets the file's size.
1727 * Returns: a #goffset containing the file's size.
1729 goffset
1730 g_file_info_get_size (GFileInfo *info)
1732 static guint32 attr = 0;
1733 GFileAttributeValue *value;
1735 g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1737 if (attr == 0)
1738 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
1740 value = g_file_info_find_value (info, attr);
1741 return (goffset) _g_file_attribute_value_get_uint64 (value);
1745 * g_file_info_get_modification_time:
1746 * @info: a #GFileInfo.
1747 * @result: (out caller-allocates): a #GTimeVal.
1749 * Gets the modification time of the current @info and sets it
1750 * in @result.
1752 void
1753 g_file_info_get_modification_time (GFileInfo *info,
1754 GTimeVal *result)
1756 static guint32 attr_mtime = 0, attr_mtime_usec;
1757 GFileAttributeValue *value;
1759 g_return_if_fail (G_IS_FILE_INFO (info));
1760 g_return_if_fail (result != NULL);
1762 if (attr_mtime == 0)
1764 attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1765 attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1768 value = g_file_info_find_value (info, attr_mtime);
1769 result->tv_sec = _g_file_attribute_value_get_uint64 (value);
1770 value = g_file_info_find_value (info, attr_mtime_usec);
1771 result->tv_usec = _g_file_attribute_value_get_uint32 (value);
1775 * g_file_info_get_symlink_target:
1776 * @info: a #GFileInfo.
1778 * Gets the symlink target for a given #GFileInfo.
1780 * Returns: a string containing the symlink target.
1782 const char *
1783 g_file_info_get_symlink_target (GFileInfo *info)
1785 static guint32 attr = 0;
1786 GFileAttributeValue *value;
1788 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1790 if (attr == 0)
1791 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
1793 value = g_file_info_find_value (info, attr);
1794 return _g_file_attribute_value_get_byte_string (value);
1798 * g_file_info_get_etag:
1799 * @info: a #GFileInfo.
1801 * Gets the [entity tag][gfile-etag] for a given
1802 * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
1804 * Returns: a string containing the value of the "etag:value" attribute.
1806 const char *
1807 g_file_info_get_etag (GFileInfo *info)
1809 static guint32 attr = 0;
1810 GFileAttributeValue *value;
1812 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1814 if (attr == 0)
1815 attr = lookup_attribute (G_FILE_ATTRIBUTE_ETAG_VALUE);
1817 value = g_file_info_find_value (info, attr);
1818 return _g_file_attribute_value_get_string (value);
1822 * g_file_info_get_sort_order:
1823 * @info: a #GFileInfo.
1825 * Gets the value of the sort_order attribute from the #GFileInfo.
1826 * See %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
1828 * Returns: a #gint32 containing the value of the "standard::sort_order" attribute.
1830 gint32
1831 g_file_info_get_sort_order (GFileInfo *info)
1833 static guint32 attr = 0;
1834 GFileAttributeValue *value;
1836 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1838 if (attr == 0)
1839 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
1841 value = g_file_info_find_value (info, attr);
1842 return _g_file_attribute_value_get_int32 (value);
1845 /* Helper setters: */
1847 * g_file_info_set_file_type:
1848 * @info: a #GFileInfo.
1849 * @type: a #GFileType.
1851 * Sets the file type in a #GFileInfo to @type.
1852 * See %G_FILE_ATTRIBUTE_STANDARD_TYPE.
1854 void
1855 g_file_info_set_file_type (GFileInfo *info,
1856 GFileType type)
1858 static guint32 attr = 0;
1859 GFileAttributeValue *value;
1861 g_return_if_fail (G_IS_FILE_INFO (info));
1863 if (attr == 0)
1864 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
1866 value = g_file_info_create_value (info, attr);
1867 if (value)
1868 _g_file_attribute_value_set_uint32 (value, type);
1872 * g_file_info_set_is_hidden:
1873 * @info: a #GFileInfo.
1874 * @is_hidden: a #gboolean.
1876 * Sets the "is_hidden" attribute in a #GFileInfo according to @is_hidden.
1877 * See %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
1879 void
1880 g_file_info_set_is_hidden (GFileInfo *info,
1881 gboolean is_hidden)
1883 static guint32 attr = 0;
1884 GFileAttributeValue *value;
1886 g_return_if_fail (G_IS_FILE_INFO (info));
1888 if (attr == 0)
1889 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
1891 value = g_file_info_create_value (info, attr);
1892 if (value)
1893 _g_file_attribute_value_set_boolean (value, is_hidden);
1897 * g_file_info_set_is_symlink:
1898 * @info: a #GFileInfo.
1899 * @is_symlink: a #gboolean.
1901 * Sets the "is_symlink" attribute in a #GFileInfo according to @is_symlink.
1902 * See %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
1904 void
1905 g_file_info_set_is_symlink (GFileInfo *info,
1906 gboolean is_symlink)
1908 static guint32 attr = 0;
1909 GFileAttributeValue *value;
1911 g_return_if_fail (G_IS_FILE_INFO (info));
1913 if (attr == 0)
1914 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
1916 value = g_file_info_create_value (info, attr);
1917 if (value)
1918 _g_file_attribute_value_set_boolean (value, is_symlink);
1922 * g_file_info_set_name:
1923 * @info: a #GFileInfo.
1924 * @name: (type filename): a string containing a name.
1926 * Sets the name attribute for the current #GFileInfo.
1927 * See %G_FILE_ATTRIBUTE_STANDARD_NAME.
1929 void
1930 g_file_info_set_name (GFileInfo *info,
1931 const char *name)
1933 static guint32 attr = 0;
1934 GFileAttributeValue *value;
1936 g_return_if_fail (G_IS_FILE_INFO (info));
1937 g_return_if_fail (name != NULL);
1939 if (attr == 0)
1940 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
1942 value = g_file_info_create_value (info, attr);
1943 if (value)
1944 _g_file_attribute_value_set_byte_string (value, name);
1948 * g_file_info_set_display_name:
1949 * @info: a #GFileInfo.
1950 * @display_name: a string containing a display name.
1952 * Sets the display name for the current #GFileInfo.
1953 * See %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
1955 void
1956 g_file_info_set_display_name (GFileInfo *info,
1957 const char *display_name)
1959 static guint32 attr = 0;
1960 GFileAttributeValue *value;
1962 g_return_if_fail (G_IS_FILE_INFO (info));
1963 g_return_if_fail (display_name != NULL);
1965 if (attr == 0)
1966 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
1968 value = g_file_info_create_value (info, attr);
1969 if (value)
1970 _g_file_attribute_value_set_string (value, display_name);
1974 * g_file_info_set_edit_name:
1975 * @info: a #GFileInfo.
1976 * @edit_name: a string containing an edit name.
1978 * Sets the edit name for the current file.
1979 * See %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
1981 void
1982 g_file_info_set_edit_name (GFileInfo *info,
1983 const char *edit_name)
1985 static guint32 attr = 0;
1986 GFileAttributeValue *value;
1988 g_return_if_fail (G_IS_FILE_INFO (info));
1989 g_return_if_fail (edit_name != NULL);
1991 if (attr == 0)
1992 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
1994 value = g_file_info_create_value (info, attr);
1995 if (value)
1996 _g_file_attribute_value_set_string (value, edit_name);
2000 * g_file_info_set_icon:
2001 * @info: a #GFileInfo.
2002 * @icon: a #GIcon.
2004 * Sets the icon for a given #GFileInfo.
2005 * See %G_FILE_ATTRIBUTE_STANDARD_ICON.
2007 void
2008 g_file_info_set_icon (GFileInfo *info,
2009 GIcon *icon)
2011 static guint32 attr = 0;
2012 GFileAttributeValue *value;
2014 g_return_if_fail (G_IS_FILE_INFO (info));
2015 g_return_if_fail (G_IS_ICON (icon));
2017 if (attr == 0)
2018 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
2020 value = g_file_info_create_value (info, attr);
2021 if (value)
2022 _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2026 * g_file_info_set_symbolic_icon:
2027 * @info: a #GFileInfo.
2028 * @icon: a #GIcon.
2030 * Sets the symbolic icon for a given #GFileInfo.
2031 * See %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
2033 * Since: 2.34
2035 void
2036 g_file_info_set_symbolic_icon (GFileInfo *info,
2037 GIcon *icon)
2039 static guint32 attr = 0;
2040 GFileAttributeValue *value;
2042 g_return_if_fail (G_IS_FILE_INFO (info));
2043 g_return_if_fail (G_IS_ICON (icon));
2045 if (attr == 0)
2046 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON);
2048 value = g_file_info_create_value (info, attr);
2049 if (value)
2050 _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2054 * g_file_info_set_content_type:
2055 * @info: a #GFileInfo.
2056 * @content_type: a content type. See [GContentType][gio-GContentType]
2058 * Sets the content type attribute for a given #GFileInfo.
2059 * See %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
2061 void
2062 g_file_info_set_content_type (GFileInfo *info,
2063 const char *content_type)
2065 static guint32 attr = 0;
2066 GFileAttributeValue *value;
2068 g_return_if_fail (G_IS_FILE_INFO (info));
2069 g_return_if_fail (content_type != NULL);
2071 if (attr == 0)
2072 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
2074 value = g_file_info_create_value (info, attr);
2075 if (value)
2076 _g_file_attribute_value_set_string (value, content_type);
2080 * g_file_info_set_size:
2081 * @info: a #GFileInfo.
2082 * @size: a #goffset containing the file's size.
2084 * Sets the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in the file info
2085 * to the given size.
2087 void
2088 g_file_info_set_size (GFileInfo *info,
2089 goffset size)
2091 static guint32 attr = 0;
2092 GFileAttributeValue *value;
2094 g_return_if_fail (G_IS_FILE_INFO (info));
2096 if (attr == 0)
2097 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
2099 value = g_file_info_create_value (info, attr);
2100 if (value)
2101 _g_file_attribute_value_set_uint64 (value, size);
2105 * g_file_info_set_modification_time:
2106 * @info: a #GFileInfo.
2107 * @mtime: a #GTimeVal.
2109 * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED attribute in the file
2110 * info to the given time value.
2112 void
2113 g_file_info_set_modification_time (GFileInfo *info,
2114 GTimeVal *mtime)
2116 static guint32 attr_mtime = 0, attr_mtime_usec;
2117 GFileAttributeValue *value;
2119 g_return_if_fail (G_IS_FILE_INFO (info));
2120 g_return_if_fail (mtime != NULL);
2122 if (attr_mtime == 0)
2124 attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2125 attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2128 value = g_file_info_create_value (info, attr_mtime);
2129 if (value)
2130 _g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
2131 value = g_file_info_create_value (info, attr_mtime_usec);
2132 if (value)
2133 _g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
2137 * g_file_info_set_symlink_target:
2138 * @info: a #GFileInfo.
2139 * @symlink_target: a static string containing a path to a symlink target.
2141 * Sets the %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET attribute in the file info
2142 * to the given symlink target.
2144 void
2145 g_file_info_set_symlink_target (GFileInfo *info,
2146 const char *symlink_target)
2148 static guint32 attr = 0;
2149 GFileAttributeValue *value;
2151 g_return_if_fail (G_IS_FILE_INFO (info));
2152 g_return_if_fail (symlink_target != NULL);
2154 if (attr == 0)
2155 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
2157 value = g_file_info_create_value (info, attr);
2158 if (value)
2159 _g_file_attribute_value_set_byte_string (value, symlink_target);
2163 * g_file_info_set_sort_order:
2164 * @info: a #GFileInfo.
2165 * @sort_order: a sort order integer.
2167 * Sets the sort order attribute in the file info structure. See
2168 * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2170 void
2171 g_file_info_set_sort_order (GFileInfo *info,
2172 gint32 sort_order)
2174 static guint32 attr = 0;
2175 GFileAttributeValue *value;
2177 g_return_if_fail (G_IS_FILE_INFO (info));
2179 if (attr == 0)
2180 attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
2182 value = g_file_info_create_value (info, attr);
2183 if (value)
2184 _g_file_attribute_value_set_int32 (value, sort_order);
2188 typedef struct {
2189 guint32 id;
2190 guint32 mask;
2191 } SubMatcher;
2193 struct _GFileAttributeMatcher {
2194 gboolean all;
2195 gint ref;
2197 GArray *sub_matchers;
2199 /* Interator */
2200 guint32 iterator_ns;
2201 gint iterator_pos;
2204 G_DEFINE_BOXED_TYPE (GFileAttributeMatcher, g_file_attribute_matcher,
2205 g_file_attribute_matcher_ref,
2206 g_file_attribute_matcher_unref)
2208 static gint
2209 compare_sub_matchers (gconstpointer a,
2210 gconstpointer b)
2212 const SubMatcher *suba = a;
2213 const SubMatcher *subb = b;
2214 int diff;
2216 diff = suba->id - subb->id;
2218 if (diff)
2219 return diff;
2221 return suba->mask - subb->mask;
2224 static gboolean
2225 sub_matcher_matches (SubMatcher *matcher,
2226 SubMatcher *submatcher)
2228 if ((matcher->mask & submatcher->mask) != matcher->mask)
2229 return FALSE;
2231 return matcher->id == (submatcher->id & matcher->mask);
2234 /* Call this function after modifying a matcher.
2235 * It will ensure all the invariants other functions rely on.
2237 static GFileAttributeMatcher *
2238 matcher_optimize (GFileAttributeMatcher *matcher)
2240 SubMatcher *submatcher, *compare;
2241 guint i, j;
2243 /* remove sub_matchers if we match everything anyway */
2244 if (matcher->all)
2246 if (matcher->sub_matchers)
2248 g_array_free (matcher->sub_matchers, TRUE);
2249 matcher->sub_matchers = NULL;
2251 return matcher;
2254 if (matcher->sub_matchers->len == 0)
2256 g_file_attribute_matcher_unref (matcher);
2257 return NULL;
2260 /* sort sub_matchers by id (and then mask), so we can bsearch
2261 * and compare matchers in O(N) instead of O(N²) */
2262 g_array_sort (matcher->sub_matchers, compare_sub_matchers);
2264 /* remove duplicates and specific matches when we match the whole namespace */
2265 j = 0;
2266 compare = &g_array_index (matcher->sub_matchers, SubMatcher, j);
2268 for (i = 1; i < matcher->sub_matchers->len; i++)
2270 submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
2271 if (sub_matcher_matches (compare, submatcher))
2272 continue;
2274 j++;
2275 compare++;
2277 if (j < i)
2278 *compare = *submatcher;
2281 g_array_set_size (matcher->sub_matchers, j + 1);
2283 return matcher;
2287 * g_file_attribute_matcher_new:
2288 * @attributes: an attribute string to match.
2290 * Creates a new file attribute matcher, which matches attributes
2291 * against a given string. #GFileAttributeMatchers are reference
2292 * counted structures, and are created with a reference count of 1. If
2293 * the number of references falls to 0, the #GFileAttributeMatcher is
2294 * automatically destroyed.
2296 * The @attribute string should be formatted with specific keys separated
2297 * from namespaces with a double colon. Several "namespace::key" strings may be
2298 * concatenated with a single comma (e.g. "standard::type,standard::is-hidden").
2299 * The wildcard "*" may be used to match all keys and namespaces, or
2300 * "namespace::*" will match all keys in a given namespace.
2302 * ## Examples of file attribute matcher strings and results
2304 * - `"*"`: matches all attributes.
2305 * - `"standard::is-hidden"`: matches only the key is-hidden in the
2306 * standard namespace.
2307 * - `"standard::type,unix::*"`: matches the type key in the standard
2308 * namespace and all keys in the unix namespace.
2310 * Returns: a #GFileAttributeMatcher
2312 GFileAttributeMatcher *
2313 g_file_attribute_matcher_new (const char *attributes)
2315 char **split;
2316 char *colon;
2317 int i;
2318 GFileAttributeMatcher *matcher;
2320 if (attributes == NULL || *attributes == '\0')
2321 return NULL;
2323 matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
2324 matcher->ref = 1;
2325 matcher->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2327 split = g_strsplit (attributes, ",", -1);
2329 for (i = 0; split[i] != NULL; i++)
2331 if (strcmp (split[i], "*") == 0)
2332 matcher->all = TRUE;
2333 else
2335 SubMatcher s;
2337 colon = strstr (split[i], "::");
2338 if (colon != NULL &&
2339 !(colon[2] == 0 ||
2340 (colon[2] == '*' &&
2341 colon[3] == 0)))
2343 s.id = lookup_attribute (split[i]);
2344 s.mask = 0xffffffff;
2346 else
2348 if (colon)
2349 *colon = 0;
2351 s.id = lookup_namespace (split[i]) << NS_POS;
2352 s.mask = NS_MASK << NS_POS;
2355 g_array_append_val (matcher->sub_matchers, s);
2359 g_strfreev (split);
2361 matcher = matcher_optimize (matcher);
2363 return matcher;
2367 * g_file_attribute_matcher_subtract:
2368 * @matcher: Matcher to subtract from
2369 * @subtract: The matcher to subtract
2371 * Subtracts all attributes of @subtract from @matcher and returns
2372 * a matcher that supports those attributes.
2374 * Note that currently it is not possible to remove a single
2375 * attribute when the @matcher matches the whole namespace - or remove
2376 * a namespace or attribute when the matcher matches everything. This
2377 * is a limitation of the current implementation, but may be fixed
2378 * in the future.
2380 * Returns: A file attribute matcher matching all attributes of
2381 * @matcher that are not matched by @subtract
2383 GFileAttributeMatcher *
2384 g_file_attribute_matcher_subtract (GFileAttributeMatcher *matcher,
2385 GFileAttributeMatcher *subtract)
2387 GFileAttributeMatcher *result;
2388 guint mi, si;
2389 SubMatcher *msub, *ssub;
2391 if (matcher == NULL)
2392 return NULL;
2393 if (subtract == NULL)
2394 return g_file_attribute_matcher_ref (matcher);
2395 if (subtract->all)
2396 return NULL;
2397 if (matcher->all)
2398 return g_file_attribute_matcher_ref (matcher);
2400 result = g_malloc0 (sizeof (GFileAttributeMatcher));
2401 result->ref = 1;
2402 result->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2404 si = 0;
2405 g_assert (subtract->sub_matchers->len > 0);
2406 ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2408 for (mi = 0; mi < matcher->sub_matchers->len; mi++)
2410 msub = &g_array_index (matcher->sub_matchers, SubMatcher, mi);
2412 retry:
2413 if (sub_matcher_matches (ssub, msub))
2414 continue;
2416 si++;
2417 if (si >= subtract->sub_matchers->len)
2418 break;
2420 ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2421 if (ssub->id <= msub->id)
2422 goto retry;
2424 g_array_append_val (result->sub_matchers, *msub);
2427 if (mi < matcher->sub_matchers->len)
2428 g_array_append_vals (result->sub_matchers,
2429 &g_array_index (matcher->sub_matchers, SubMatcher, mi),
2430 matcher->sub_matchers->len - mi);
2432 result = matcher_optimize (result);
2434 return result;
2438 * g_file_attribute_matcher_ref:
2439 * @matcher: a #GFileAttributeMatcher.
2441 * References a file attribute matcher.
2443 * Returns: a #GFileAttributeMatcher.
2445 GFileAttributeMatcher *
2446 g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
2448 if (matcher)
2450 g_return_val_if_fail (matcher->ref > 0, NULL);
2451 g_atomic_int_inc (&matcher->ref);
2453 return matcher;
2457 * g_file_attribute_matcher_unref:
2458 * @matcher: a #GFileAttributeMatcher.
2460 * Unreferences @matcher. If the reference count falls below 1,
2461 * the @matcher is automatically freed.
2464 void
2465 g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
2467 if (matcher)
2469 g_return_if_fail (matcher->ref > 0);
2471 if (g_atomic_int_dec_and_test (&matcher->ref))
2473 if (matcher->sub_matchers)
2474 g_array_free (matcher->sub_matchers, TRUE);
2476 g_free (matcher);
2482 * g_file_attribute_matcher_matches_only:
2483 * @matcher: a #GFileAttributeMatcher.
2484 * @attribute: a file attribute key.
2486 * Checks if a attribute matcher only matches a given attribute. Always
2487 * returns %FALSE if "*" was used when creating the matcher.
2489 * Returns: %TRUE if the matcher only matches @attribute. %FALSE otherwise.
2491 gboolean
2492 g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
2493 const char *attribute)
2495 SubMatcher *sub_matcher;
2496 guint32 id;
2498 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2500 if (matcher == NULL ||
2501 matcher->all)
2502 return FALSE;
2504 if (matcher->sub_matchers->len != 1)
2505 return FALSE;
2507 id = lookup_attribute (attribute);
2509 sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, 0);
2511 return sub_matcher->id == id &&
2512 sub_matcher->mask == 0xffffffff;
2515 static gboolean
2516 matcher_matches_id (GFileAttributeMatcher *matcher,
2517 guint32 id)
2519 SubMatcher *sub_matchers;
2520 int i;
2522 if (matcher->sub_matchers)
2524 sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
2525 for (i = 0; i < matcher->sub_matchers->len; i++)
2527 if (sub_matchers[i].id == (id & sub_matchers[i].mask))
2528 return TRUE;
2532 return FALSE;
2535 gboolean
2536 _g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
2537 guint32 id)
2539 /* We return a NULL matcher for an empty match string, so handle this */
2540 if (matcher == NULL)
2541 return FALSE;
2543 if (matcher->all)
2544 return TRUE;
2546 return matcher_matches_id (matcher, id);
2550 * g_file_attribute_matcher_matches:
2551 * @matcher: a #GFileAttributeMatcher.
2552 * @attribute: a file attribute key.
2554 * Checks if an attribute will be matched by an attribute matcher. If
2555 * the matcher was created with the "*" matching string, this function
2556 * will always return %TRUE.
2558 * Returns: %TRUE if @attribute matches @matcher. %FALSE otherwise.
2560 gboolean
2561 g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
2562 const char *attribute)
2564 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2566 /* We return a NULL matcher for an empty match string, so handle this */
2567 if (matcher == NULL)
2568 return FALSE;
2570 if (matcher->all)
2571 return TRUE;
2573 return matcher_matches_id (matcher, lookup_attribute (attribute));
2576 /* return TRUE -> all */
2578 * g_file_attribute_matcher_enumerate_namespace:
2579 * @matcher: a #GFileAttributeMatcher.
2580 * @ns: a string containing a file attribute namespace.
2582 * Checks if the matcher will match all of the keys in a given namespace.
2583 * This will always return %TRUE if a wildcard character is in use (e.g. if
2584 * matcher was created with "standard::*" and @ns is "standard", or if matcher was created
2585 * using "*" and namespace is anything.)
2587 * TODO: this is awkwardly worded.
2589 * Returns: %TRUE if the matcher matches all of the entries
2590 * in the given @ns, %FALSE otherwise.
2592 gboolean
2593 g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
2594 const char *ns)
2596 SubMatcher *sub_matchers;
2597 int ns_id;
2598 int i;
2600 g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
2602 /* We return a NULL matcher for an empty match string, so handle this */
2603 if (matcher == NULL)
2604 return FALSE;
2606 if (matcher->all)
2607 return TRUE;
2609 ns_id = lookup_namespace (ns) << NS_POS;
2611 if (matcher->sub_matchers)
2613 sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
2614 for (i = 0; i < matcher->sub_matchers->len; i++)
2616 if (sub_matchers[i].id == ns_id)
2617 return TRUE;
2621 matcher->iterator_ns = ns_id;
2622 matcher->iterator_pos = 0;
2624 return FALSE;
2628 * g_file_attribute_matcher_enumerate_next:
2629 * @matcher: a #GFileAttributeMatcher.
2631 * Gets the next matched attribute from a #GFileAttributeMatcher.
2633 * Returns: a string containing the next attribute or %NULL if
2634 * no more attribute exist.
2636 const char *
2637 g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
2639 int i;
2640 SubMatcher *sub_matcher;
2642 /* We return a NULL matcher for an empty match string, so handle this */
2643 if (matcher == NULL)
2644 return NULL;
2646 while (1)
2648 i = matcher->iterator_pos++;
2650 if (matcher->sub_matchers == NULL)
2651 return NULL;
2653 if (i < matcher->sub_matchers->len)
2654 sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
2655 else
2656 return NULL;
2658 if (sub_matcher->mask == 0xffffffff &&
2659 (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
2660 return get_attribute_for_id (sub_matcher->id);
2665 * g_file_attribute_matcher_to_string:
2666 * @matcher: (nullable): a #GFileAttributeMatcher.
2668 * Prints what the matcher is matching against. The format will be
2669 * equal to the format passed to g_file_attribute_matcher_new().
2670 * The output however, might not be identical, as the matcher may
2671 * decide to use a different order or omit needless parts.
2673 * Returns: a string describing the attributes the matcher matches
2674 * against or %NULL if @matcher was %NULL.
2676 * Since: 2.32
2678 char *
2679 g_file_attribute_matcher_to_string (GFileAttributeMatcher *matcher)
2681 GString *string;
2682 guint i;
2684 if (matcher == NULL)
2685 return NULL;
2687 if (matcher->all)
2688 return g_strdup ("*");
2690 string = g_string_new ("");
2691 for (i = 0; i < matcher->sub_matchers->len; i++)
2693 SubMatcher *submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
2695 if (i > 0)
2696 g_string_append_c (string, ',');
2698 g_string_append (string, get_attribute_for_id (submatcher->id));
2701 return g_string_free (string, FALSE);