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 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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Alexander Larsson <alexl@redhat.com>
27 #include "gfileinfo.h"
30 /* We use this nasty thing, because NULL is a valid attribute matcher (matches nothing) */
31 #define NO_ATTRIBUTE_MASK ((GFileAttributeMatcher *)1)
35 GFileAttributeValue value;
40 GObject parent_instance;
43 GFileAttributeMatcher *mask;
46 struct _GFileInfoClass
48 GObjectClass parent_class;
51 static gboolean g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
54 G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT);
58 guint32 attribute_id_counter;
61 G_LOCK_DEFINE_STATIC (attribute_hash);
62 static int namespace_id_counter = 0;
63 static GHashTable *ns_hash = NULL;
64 static GHashTable *attribute_hash = NULL;
65 static char ***attributes = NULL;
67 /* Attribute ids are 32bit, we split it up like this:
68 * |------------|--------------------|
70 * namespace attribute id
72 * This way the attributes gets sorted in namespace order
76 #define NS_MASK ((guint32)((1<<12) - 1))
78 #define ID_MASK ((guint32)((1<<20) - 1))
80 #define GET_NS(_attr_id) \
81 (((guint32) (_attr_id) >> NS_POS) & NS_MASK)
82 #define GET_ID(_attr_id) \
83 (((guint32)(_attr_id) >> ID_POS) & ID_MASK)
85 #define MAKE_ATTR_ID(_ns, _id) \
86 ( ((((guint32) _ns) & NS_MASK) << NS_POS) | \
87 ((((guint32) _id) & ID_MASK) << ID_POS) )
90 _lookup_namespace (const char *namespace)
94 ns_info = g_hash_table_lookup (ns_hash, namespace);
97 ns_info = g_new0 (NSInfo, 1);
98 ns_info->id = ++namespace_id_counter;
99 g_hash_table_insert (ns_hash, g_strdup (namespace), ns_info);
100 attributes = g_realloc (attributes, (ns_info->id + 1) * sizeof (char **));
101 attributes[ns_info->id] = NULL;
107 lookup_namespace (const char *namespace)
112 G_LOCK (attribute_hash);
114 if (attribute_hash == NULL)
116 ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
117 attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
120 ns_info = _lookup_namespace (namespace);
125 G_UNLOCK (attribute_hash);
131 get_attribute_for_id (int attribute)
134 G_LOCK (attribute_hash);
135 s = attributes[GET_NS(attribute)][GET_ID(attribute)];
136 G_UNLOCK (attribute_hash);
141 lookup_attribute (const char *attribute)
148 G_LOCK (attribute_hash);
149 if (attribute_hash == NULL)
151 ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
152 attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
155 attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute));
159 G_UNLOCK (attribute_hash);
163 colon = strchr (attribute, ':');
165 ns = g_strndup (attribute, colon - attribute);
169 ns_info = _lookup_namespace (ns);
172 id = ++ns_info->attribute_id_counter;
173 attributes[ns_info->id] = g_realloc (attributes[ns_info->id], (id + 1) * sizeof (char *));
174 attributes[ns_info->id][id] = g_strdup (attribute);
176 attr_id = MAKE_ATTR_ID (ns_info->id, id);
178 g_hash_table_insert (attribute_hash, attributes[ns_info->id][id], GUINT_TO_POINTER (attr_id));
180 G_UNLOCK (attribute_hash);
186 g_file_info_finalize (GObject *object)
190 GFileAttribute *attrs;
192 info = G_FILE_INFO (object);
194 attrs = (GFileAttribute *)info->attributes->data;
195 for (i = 0; i < info->attributes->len; i++)
196 g_file_attribute_value_clear (&attrs[i].value);
197 g_array_free (info->attributes, TRUE);
199 if (info->mask != NO_ATTRIBUTE_MASK)
200 g_file_attribute_matcher_unref (info->mask);
202 if (G_OBJECT_CLASS (g_file_info_parent_class)->finalize)
203 (*G_OBJECT_CLASS (g_file_info_parent_class)->finalize) (object);
207 g_file_info_class_init (GFileInfoClass *klass)
209 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
211 gobject_class->finalize = g_file_info_finalize;
215 g_file_info_init (GFileInfo *info)
217 info->mask = NO_ATTRIBUTE_MASK;
218 info->attributes = g_array_new (FALSE, FALSE,
219 sizeof (GFileAttribute));
225 * Returns: a new #GFileInfo.
228 g_file_info_new (void)
230 return g_object_new (G_TYPE_FILE_INFO, NULL);
234 * g_file_info_copy_into:
235 * @src_info: source to copy attributes from.
236 * @dest_info: destination to copy attributes to.
238 * Copies all of the attributes from @src_info to @dest_info.
241 g_file_info_copy_into (GFileInfo *src_info, GFileInfo *dest_info)
243 GFileAttribute *source, *dest;
246 g_return_if_fail (G_IS_FILE_INFO (src_info));
247 g_return_if_fail (G_IS_FILE_INFO (dest_info));
249 dest = (GFileAttribute *)dest_info->attributes->data;
250 for (i = 0; i < dest_info->attributes->len; i++)
251 g_file_attribute_value_clear (&dest[i].value);
253 g_array_set_size (dest_info->attributes,
254 src_info->attributes->len);
256 source = (GFileAttribute *)src_info->attributes->data;
257 dest = (GFileAttribute *)dest_info->attributes->data;
259 for (i = 0; i < src_info->attributes->len; i++)
261 dest[i].attribute = source[i].attribute;
262 dest[i].value.type = G_FILE_ATTRIBUTE_TYPE_INVALID;
263 g_file_attribute_value_set (&dest[i].value, &source[i].value);
266 if (src_info->mask == NO_ATTRIBUTE_MASK)
267 dest_info->mask = NO_ATTRIBUTE_MASK;
269 dest_info->mask = g_file_attribute_matcher_ref (src_info->mask);
274 * @other: a #GFileInfo.
276 * Returns: a duplicate #GFileInfo of @other.
279 g_file_info_dup (GFileInfo *other)
283 g_return_val_if_fail (G_IS_FILE_INFO (other), NULL);
285 new = g_file_info_new ();
286 g_file_info_copy_into (other, new);
291 * g_file_info_set_attribute_mask:
292 * @info: a #GFileInfo.
293 * @mask: a #GFileAttributeMatcher.
295 * Sets @mask on @info to match specific attribute types.
299 g_file_info_set_attribute_mask (GFileInfo *info,
300 GFileAttributeMatcher *mask)
302 GFileAttribute *attr;
305 g_return_if_fail (G_IS_FILE_INFO (info));
306 g_return_if_fail (mask != NULL);
308 if (mask != info->mask)
310 if (info->mask != NO_ATTRIBUTE_MASK)
311 g_file_attribute_matcher_unref (info->mask);
312 info->mask = g_file_attribute_matcher_ref (mask);
314 /* Remove non-matching attributes */
315 for (i = 0; i < info->attributes->len; i++)
317 attr = &g_array_index (info->attributes, GFileAttribute, i);
318 if (!g_file_attribute_matcher_matches_id (mask,
321 g_file_attribute_value_clear (&attr->value);
322 g_array_remove_index (info->attributes, i);
330 * g_file_info_unset_attribute_mask:
335 g_file_info_unset_attribute_mask (GFileInfo *info)
337 g_return_if_fail (G_IS_FILE_INFO (info));
339 if (info->mask != NO_ATTRIBUTE_MASK)
340 g_file_attribute_matcher_unref (info->mask);
341 info->mask = NO_ATTRIBUTE_MASK;
345 * g_file_info_clear_status:
346 * @info: a #GFileInfo.
348 * Clears the status information from @info.
352 g_file_info_clear_status (GFileInfo *info)
354 GFileAttribute *attrs;
357 g_return_if_fail (G_IS_FILE_INFO (info));
359 attrs = (GFileAttribute *)info->attributes->data;
360 for (i = 0; i < info->attributes->len; i++)
361 attrs[i].value.status = G_FILE_ATTRIBUTE_STATUS_UNSET;
365 g_file_info_find_place (GFileInfo *info,
369 GFileAttribute *attrs;
370 /* Binary search for the place where attribute would be, if its
374 max = info->attributes->len;
376 attrs = (GFileAttribute *)info->attributes->data;
380 med = min + (max - min) / 2;
381 if (attrs[med].attribute == attribute)
386 else if (attrs[med].attribute < attribute)
388 else /* attrs[med].attribute > attribute */
395 static GFileAttributeValue *
396 g_file_info_find_value (GFileInfo *info,
399 GFileAttribute *attrs;
402 i = g_file_info_find_place (info, attr_id);
403 attrs = (GFileAttribute *)info->attributes->data;
404 if (i < info->attributes->len &&
405 attrs[i].attribute == attr_id)
406 return &attrs[i].value;
411 static GFileAttributeValue *
412 g_file_info_find_value_by_name (GFileInfo *info,
413 const char *attribute)
417 attr_id = lookup_attribute (attribute);
418 return g_file_info_find_value (info, attr_id);
422 * g_file_info_has_attribute:
423 * @info: a #GFileInfo.
424 * @attribute: a string.
426 * Returns: %TRUE if @GFileInfo has an attribute named @attribute,
430 g_file_info_has_attribute (GFileInfo *info,
431 const char *attribute)
433 GFileAttributeValue *value;
435 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
436 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
438 value = g_file_info_find_value_by_name (info, attribute);
439 return value != NULL;
443 * g_file_info_list_attributes:
444 * @info: a #GFileInfo.
445 * @name_space: a string.
447 * Returns: a null-terminated array of strings of all of the
448 * possible attribute types for the given @name_space, or
452 g_file_info_list_attributes (GFileInfo *info,
453 const char *name_space)
456 GFileAttribute *attrs;
458 guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0;
461 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
463 names = g_ptr_array_new ();
464 attrs = (GFileAttribute *)info->attributes->data;
465 for (i = 0; i < info->attributes->len; i++)
467 attribute = attrs[i].attribute;
468 if (ns_id == 0 || GET_NS (attribute) == ns_id)
469 g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute)));
473 g_ptr_array_add (names, NULL);
475 return (char **)g_ptr_array_free (names, FALSE);
479 * g_file_info_get_attribute_type:
480 * @info: a #GFileInfo.
481 * @attribute: a string.
483 * Returns: a #GFileAttributeType for the given @attribute, or
484 * %G_FILE_ATTRIBUTE_TYPE_INVALID if one cannot be found.
487 g_file_info_get_attribute_type (GFileInfo *info,
488 const char *attribute)
490 GFileAttributeValue *value;
492 g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_ATTRIBUTE_TYPE_INVALID);
493 g_return_val_if_fail (attribute != NULL && *attribute != '\0', G_FILE_ATTRIBUTE_TYPE_INVALID);
495 value = g_file_info_find_value_by_name (info, attribute);
499 return G_FILE_ATTRIBUTE_TYPE_INVALID;
503 * g_file_info_remove_attribute:
504 * @info: a #GFileInfo.
505 * @attribute: a string.
507 * Removes @attribute from @info if it exists.
511 g_file_info_remove_attribute (GFileInfo *info,
512 const char *attribute)
515 GFileAttribute *attrs;
518 g_return_if_fail (G_IS_FILE_INFO (info));
519 g_return_if_fail (attribute != NULL && *attribute != '\0');
521 attr_id = lookup_attribute (attribute);
523 i = g_file_info_find_place (info, attr_id);
524 attrs = (GFileAttribute *)info->attributes->data;
525 if (i < info->attributes->len &&
526 attrs[i].attribute == attr_id)
528 g_file_attribute_value_clear (&attrs[i].value);
529 g_array_remove_index (info->attributes, i);
534 * g_file_info_get_attribute:
535 * @info: a #GFileInfo.
536 * @attribute: a string.
538 * Returns: a #GFileAttributeValue for the given @attribute, or
541 GFileAttributeValue *
542 g_file_info_get_attribute (GFileInfo *info,
543 const char *attribute)
546 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
547 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
549 return g_file_info_find_value_by_name (info, attribute);
553 * g_file_info_get_attribute_object:
554 * @info: a #GFileInfo.
555 * @attribute: a string.
557 * Returns: a #GObject associated with the given @attribute, or
561 g_file_info_get_attribute_object (GFileInfo *info,
562 const char *attribute)
564 GFileAttributeValue *value;
566 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
567 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
569 value = g_file_info_find_value_by_name (info, attribute);
570 return g_file_attribute_value_get_object (value);
574 * g_file_info_get_attribute_string:
575 * @info: a #GFileInfo.
576 * @attribute: a string.
578 * Returns: the contents of the @attribute value as a string, or
582 g_file_info_get_attribute_string (GFileInfo *info,
583 const char *attribute)
585 GFileAttributeValue *value;
587 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
588 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
590 value = g_file_info_find_value_by_name (info, attribute);
591 return g_file_attribute_value_get_string (value);
595 * g_file_info_get_attribute_byte_string:
596 * @info: a #GFileInfo.
597 * @attribute: a string.
599 * Returns: the contents of the @attribute value as a byte string, or
603 g_file_info_get_attribute_byte_string (GFileInfo *info,
604 const char *attribute)
606 GFileAttributeValue *value;
608 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
609 g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
611 value = g_file_info_find_value_by_name (info, attribute);
612 return g_file_attribute_value_get_byte_string (value);
616 * g_file_info_get_attribute_boolean:
617 * @info: a #GFileInfo.
618 * @attribute: a string.
623 g_file_info_get_attribute_boolean (GFileInfo *info,
624 const char *attribute)
626 GFileAttributeValue *value;
628 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
629 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
631 value = g_file_info_find_value_by_name (info, attribute);
632 return g_file_attribute_value_get_boolean (value);
636 * g_file_info_get_attribute_uint32:
637 * @info: a #GFileInfo.
638 * @attribute: a string.
643 g_file_info_get_attribute_uint32 (GFileInfo *info,
644 const char *attribute)
646 GFileAttributeValue *value;
648 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
649 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
651 value = g_file_info_find_value_by_name (info, attribute);
652 return g_file_attribute_value_get_uint32 (value);
656 * g_file_info_get_attribute_int32:
663 g_file_info_get_attribute_int32 (GFileInfo *info,
664 const char *attribute)
666 GFileAttributeValue *value;
668 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
669 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
671 value = g_file_info_find_value_by_name (info, attribute);
672 return g_file_attribute_value_get_int32 (value);
676 * g_file_info_get_attribute_uint64:
683 g_file_info_get_attribute_uint64 (GFileInfo *info,
684 const char *attribute)
686 GFileAttributeValue *value;
688 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
689 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
691 value = g_file_info_find_value_by_name (info, attribute);
692 return g_file_attribute_value_get_uint64 (value);
696 * g_file_info_get_attribute_int64:
703 g_file_info_get_attribute_int64 (GFileInfo *info,
704 const char *attribute)
706 GFileAttributeValue *value;
708 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
709 g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
711 value = g_file_info_find_value_by_name (info, attribute);
712 return g_file_attribute_value_get_int64 (value);
715 static GFileAttributeValue *
716 g_file_info_create_value (GFileInfo *info,
719 GFileAttribute *attrs;
723 if (info->mask != NO_ATTRIBUTE_MASK &&
724 !g_file_attribute_matcher_matches_id (info->mask, attr_id))
727 i = g_file_info_find_place (info, attr_id);
729 attrs = (GFileAttribute *)info->attributes->data;
730 if (i < info->attributes->len &&
731 attrs[i].attribute == attr_id)
732 return &attrs[i].value;
735 attr.attribute = attr_id;
736 attr.value.type = G_FILE_ATTRIBUTE_TYPE_INVALID;
737 g_array_insert_val (info->attributes, i, attr);
739 attrs = (GFileAttribute *)info->attributes->data;
740 return &attrs[i].value;
744 static GFileAttributeValue *
745 g_file_info_create_value_by_name (GFileInfo *info,
746 const char *attribute)
750 attr_id = lookup_attribute (attribute);
752 return g_file_info_create_value (info, attr_id);
756 * g_file_info_set_attribute:
763 g_file_info_set_attribute (GFileInfo *info,
764 const char *attribute,
765 const GFileAttributeValue *attr_value)
767 GFileAttributeValue *value;
769 g_return_if_fail (G_IS_FILE_INFO (info));
770 g_return_if_fail (attribute != NULL && *attribute != '\0');
771 g_return_if_fail (attr_value != NULL);
773 value = g_file_info_create_value_by_name (info, attribute);
775 g_file_attribute_value_set (value, attr_value);
779 * g_file_info_set_attribute_object:
786 g_file_info_set_attribute_object (GFileInfo *info,
787 const char *attribute,
790 GFileAttributeValue *value;
792 g_return_if_fail (G_IS_FILE_INFO (info));
793 g_return_if_fail (attribute != NULL && *attribute != '\0');
794 g_return_if_fail (G_IS_OBJECT (attr_value));
796 value = g_file_info_create_value_by_name (info, attribute);
798 g_file_attribute_value_set_object (value, attr_value);
802 * g_file_info_set_attribute_string:
809 g_file_info_set_attribute_string (GFileInfo *info,
810 const char *attribute,
811 const char *attr_value)
813 GFileAttributeValue *value;
815 g_return_if_fail (G_IS_FILE_INFO (info));
816 g_return_if_fail (attribute != NULL && *attribute != '\0');
817 g_return_if_fail (attr_value != NULL);
819 value = g_file_info_create_value_by_name (info, attribute);
821 g_file_attribute_value_set_string (value, attr_value);
825 * g_file_info_set_attribute_byte_string:
832 g_file_info_set_attribute_byte_string (GFileInfo *info,
833 const char *attribute,
834 const char *attr_value)
836 GFileAttributeValue *value;
838 g_return_if_fail (G_IS_FILE_INFO (info));
839 g_return_if_fail (attribute != NULL && *attribute != '\0');
840 g_return_if_fail (attr_value != NULL);
842 value = g_file_info_create_value_by_name (info, attribute);
844 g_file_attribute_value_set_byte_string (value, attr_value);
848 * g_file_info_set_attribute_boolean:
855 g_file_info_set_attribute_boolean (GFileInfo *info,
856 const char *attribute,
859 GFileAttributeValue *value;
861 g_return_if_fail (G_IS_FILE_INFO (info));
862 g_return_if_fail (attribute != NULL && *attribute != '\0');
864 value = g_file_info_create_value_by_name (info, attribute);
866 g_file_attribute_value_set_boolean (value, attr_value);
870 * g_file_info_set_attribute_uint32:
878 g_file_info_set_attribute_uint32 (GFileInfo *info,
879 const char *attribute,
882 GFileAttributeValue *value;
884 g_return_if_fail (G_IS_FILE_INFO (info));
885 g_return_if_fail (attribute != NULL && *attribute != '\0');
887 value = g_file_info_create_value_by_name (info, attribute);
889 g_file_attribute_value_set_uint32 (value, attr_value);
894 * g_file_info_set_attribute_int32:
901 g_file_info_set_attribute_int32 (GFileInfo *info,
902 const char *attribute,
905 GFileAttributeValue *value;
907 g_return_if_fail (G_IS_FILE_INFO (info));
908 g_return_if_fail (attribute != NULL && *attribute != '\0');
910 value = g_file_info_create_value_by_name (info, attribute);
912 g_file_attribute_value_set_int32 (value, attr_value);
916 * g_file_info_set_attribute_uint64:
923 g_file_info_set_attribute_uint64 (GFileInfo *info,
924 const char *attribute,
927 GFileAttributeValue *value;
929 g_return_if_fail (G_IS_FILE_INFO (info));
930 g_return_if_fail (attribute != NULL && *attribute != '\0');
932 value = g_file_info_create_value_by_name (info, attribute);
934 g_file_attribute_value_set_uint64 (value, attr_value);
938 * g_file_info_set_attribute_int64:
940 * @attribute: attribute name to set.
941 * @attr_value: int64 value to set attribute to.
945 g_file_info_set_attribute_int64 (GFileInfo *info,
946 const char *attribute,
949 GFileAttributeValue *value;
951 g_return_if_fail (G_IS_FILE_INFO (info));
952 g_return_if_fail (attribute != NULL && *attribute != '\0');
954 value = g_file_info_create_value_by_name (info, attribute);
956 g_file_attribute_value_set_int64 (value, attr_value);
961 * g_file_info_get_file_type:
962 * @info: a #GFileInfo.
964 * Returns: a #GFileType for the given file.
967 g_file_info_get_file_type (GFileInfo *info)
969 static guint32 attr = 0;
970 GFileAttributeValue *value;
972 g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_TYPE_UNKNOWN);
975 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_TYPE);
977 value = g_file_info_find_value (info, attr);
978 return (GFileType)g_file_attribute_value_get_uint32 (value);
982 * g_file_info_get_is_hidden:
983 * @info: a #GFileInfo.
985 * Returns: %TRUE if the file is a hidden file, %FALSE otherwise.
988 g_file_info_get_is_hidden (GFileInfo *info)
990 static guint32 attr = 0;
991 GFileAttributeValue *value;
993 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
996 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_IS_HIDDEN);
998 value = g_file_info_find_value (info, attr);
999 return (GFileType)g_file_attribute_value_get_boolean (value);
1003 * g_file_info_get_is_backup:
1004 * @info: a #GFileInfo.
1006 * Returns: %TRUE if file is a backup file (.*~), %FALSE otherwise.
1009 g_file_info_get_is_backup (GFileInfo *info)
1011 static guint32 attr = 0;
1012 GFileAttributeValue *value;
1014 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1017 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_IS_BACKUP);
1019 value = g_file_info_find_value (info, attr);
1020 return (GFileType)g_file_attribute_value_get_boolean (value);
1024 * g_file_info_get_is_symlink:
1025 * @info: a #GFileInfo.
1027 * Returns: %TRUE if the given @info is a symlink.
1030 g_file_info_get_is_symlink (GFileInfo *info)
1032 static guint32 attr = 0;
1033 GFileAttributeValue *value;
1035 g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1038 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_IS_SYMLINK);
1040 value = g_file_info_find_value (info, attr);
1041 return (GFileType)g_file_attribute_value_get_boolean (value);
1045 * g_file_info_get_name:
1046 * @info: a #GFileInfo.
1051 g_file_info_get_name (GFileInfo *info)
1053 static guint32 attr = 0;
1054 GFileAttributeValue *value;
1056 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1059 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_NAME);
1061 value = g_file_info_find_value (info, attr);
1062 return g_file_attribute_value_get_byte_string (value);
1066 * g_file_info_get_display_name:
1067 * @info: a #GFileInfo.
1072 g_file_info_get_display_name (GFileInfo *info)
1074 static guint32 attr = 0;
1075 GFileAttributeValue *value;
1077 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1080 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_DISPLAY_NAME);
1082 value = g_file_info_find_value (info, attr);
1083 return g_file_attribute_value_get_string (value);
1087 * g_file_info_get_edit_name:
1088 * @info: a #GFileInfo.
1093 g_file_info_get_edit_name (GFileInfo *info)
1095 static guint32 attr = 0;
1096 GFileAttributeValue *value;
1098 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1101 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_EDIT_NAME);
1103 value = g_file_info_find_value (info, attr);
1104 return g_file_attribute_value_get_string (value);
1108 * g_file_info_get_icon:
1109 * @info: a #GFileInfo.
1111 * Returns: #GIcon for the given @info.
1114 g_file_info_get_icon (GFileInfo *info)
1116 static guint32 attr = 0;
1117 GFileAttributeValue *value;
1120 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1123 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ICON);
1125 value = g_file_info_find_value (info, attr);
1126 obj = g_file_attribute_value_get_object (value);
1127 if (obj != NULL && G_IS_ICON (obj))
1128 return G_ICON (obj);
1133 * g_file_info_get_content_type:
1134 * @info: a #GFileInfo.
1139 g_file_info_get_content_type (GFileInfo *info)
1141 static guint32 attr = 0;
1142 GFileAttributeValue *value;
1144 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1147 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_CONTENT_TYPE);
1149 value = g_file_info_find_value (info, attr);
1150 return g_file_attribute_value_get_string (value);
1154 * g_file_info_get_size:
1155 * @info: a #GFileInfo.
1160 g_file_info_get_size (GFileInfo *info)
1162 static guint32 attr = 0;
1163 GFileAttributeValue *value;
1165 g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1168 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SIZE);
1170 value = g_file_info_find_value (info, attr);
1171 return (goffset) g_file_attribute_value_get_uint64 (value);
1175 * g_file_info_get_modification_time:
1176 * @info: a #GFileInfo.
1182 g_file_info_get_modification_time (GFileInfo *info,
1185 static guint32 attr_mtime = 0, attr_mtime_usec;
1186 GFileAttributeValue *value;
1188 g_return_if_fail (G_IS_FILE_INFO (info));
1189 g_return_if_fail (result != NULL);
1191 if (attr_mtime == 0)
1193 attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1194 attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1197 value = g_file_info_find_value (info, attr_mtime);
1198 result->tv_sec = g_file_attribute_value_get_uint64 (value);
1199 value = g_file_info_find_value (info, attr_mtime_usec);
1200 result->tv_usec = g_file_attribute_value_get_uint32 (value);
1204 * g_file_info_get_symlink_target:
1205 * @info: a #GFileInfo.
1210 g_file_info_get_symlink_target (GFileInfo *info)
1212 static guint32 attr = 0;
1213 GFileAttributeValue *value;
1215 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1218 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET);
1220 value = g_file_info_find_value (info, attr);
1221 return g_file_attribute_value_get_byte_string (value);
1225 * g_file_info_get_etag:
1226 * @info: a #GFileInfo.
1231 g_file_info_get_etag (GFileInfo *info)
1233 static guint32 attr = 0;
1234 GFileAttributeValue *value;
1236 g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1239 attr = lookup_attribute (G_FILE_ATTRIBUTE_ETAG_VALUE);
1241 value = g_file_info_find_value (info, attr);
1242 return g_file_attribute_value_get_string (value);
1246 * g_file_info_get_sort_order:
1247 * @info: a #GFileInfo.
1252 g_file_info_get_sort_order (GFileInfo *info)
1254 static guint32 attr = 0;
1255 GFileAttributeValue *value;
1257 g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1260 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SORT_ORDER);
1262 value = g_file_info_find_value (info, attr);
1263 return g_file_attribute_value_get_int32 (value);
1266 /* Helper setters: */
1268 * g_file_info_set_file_type:
1269 * @info: a #GFileInfo.
1274 g_file_info_set_file_type (GFileInfo *info,
1277 static guint32 attr = 0;
1278 GFileAttributeValue *value;
1280 g_return_if_fail (G_IS_FILE_INFO (info));
1283 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_TYPE);
1285 value = g_file_info_create_value (info, attr);
1287 g_file_attribute_value_set_uint32 (value, type);
1291 * g_file_info_set_is_hidden:
1292 * @info: a #GFileInfo.
1297 g_file_info_set_is_hidden (GFileInfo *info,
1300 static guint32 attr = 0;
1301 GFileAttributeValue *value;
1303 g_return_if_fail (G_IS_FILE_INFO (info));
1306 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_IS_HIDDEN);
1308 value = g_file_info_create_value (info, attr);
1310 g_file_attribute_value_set_boolean (value, is_hidden);
1314 * g_file_info_set_is_symlink:
1315 * @info: a #GFileInfo.
1320 g_file_info_set_is_symlink (GFileInfo *info,
1321 gboolean is_symlink)
1323 static guint32 attr = 0;
1324 GFileAttributeValue *value;
1326 g_return_if_fail (G_IS_FILE_INFO (info));
1329 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_IS_SYMLINK);
1331 value = g_file_info_create_value (info, attr);
1333 g_file_attribute_value_set_boolean (value, is_symlink);
1337 * g_file_info_set_name:
1338 * @info: a #GFileInfo.
1343 g_file_info_set_name (GFileInfo *info,
1346 static guint32 attr = 0;
1347 GFileAttributeValue *value;
1349 g_return_if_fail (G_IS_FILE_INFO (info));
1350 g_return_if_fail (name != NULL);
1353 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_NAME);
1355 value = g_file_info_create_value (info, attr);
1357 g_file_attribute_value_set_byte_string (value, name);
1361 * g_file_info_set_display_name:
1362 * @info: a #GFileInfo.
1367 g_file_info_set_display_name (GFileInfo *info,
1368 const char *display_name)
1370 static guint32 attr = 0;
1371 GFileAttributeValue *value;
1373 g_return_if_fail (G_IS_FILE_INFO (info));
1374 g_return_if_fail (display_name != NULL);
1377 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_DISPLAY_NAME);
1379 value = g_file_info_create_value (info, attr);
1381 g_file_attribute_value_set_string (value, display_name);
1385 * g_file_info_set_edit_name:
1386 * @info: a #GFileInfo.
1392 g_file_info_set_edit_name (GFileInfo *info,
1393 const char *edit_name)
1395 static guint32 attr = 0;
1396 GFileAttributeValue *value;
1398 g_return_if_fail (G_IS_FILE_INFO (info));
1399 g_return_if_fail (edit_name != NULL);
1402 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_EDIT_NAME);
1404 value = g_file_info_create_value (info, attr);
1406 g_file_attribute_value_set_string (value, edit_name);
1410 * g_file_info_set_icon:
1411 * @info: a #GFileInfo.
1416 g_file_info_set_icon (GFileInfo *info,
1419 static guint32 attr = 0;
1420 GFileAttributeValue *value;
1422 g_return_if_fail (G_IS_FILE_INFO (info));
1423 g_return_if_fail (G_IS_ICON (icon));
1426 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ICON);
1428 value = g_file_info_create_value (info, attr);
1430 g_file_attribute_value_set_object (value, G_OBJECT (icon));
1434 * g_file_info_set_content_type:
1435 * @info: a #GFileInfo.
1440 g_file_info_set_content_type (GFileInfo *info,
1441 const char *content_type)
1443 static guint32 attr = 0;
1444 GFileAttributeValue *value;
1446 g_return_if_fail (G_IS_FILE_INFO (info));
1447 g_return_if_fail (content_type != NULL);
1450 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_CONTENT_TYPE);
1452 value = g_file_info_create_value (info, attr);
1454 g_file_attribute_value_set_string (value, content_type);
1458 * g_file_info_set_size:
1459 * @info: a #GFileInfo.
1464 g_file_info_set_size (GFileInfo *info,
1467 static guint32 attr = 0;
1468 GFileAttributeValue *value;
1470 g_return_if_fail (G_IS_FILE_INFO (info));
1473 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SIZE);
1475 value = g_file_info_create_value (info, attr);
1477 g_file_attribute_value_set_uint64 (value, size);
1481 * g_file_info_set_modification_time
1482 * @info: a #GFileInfo.
1487 g_file_info_set_modification_time (GFileInfo *info,
1490 static guint32 attr_mtime = 0, attr_mtime_usec;
1491 GFileAttributeValue *value;
1493 g_return_if_fail (G_IS_FILE_INFO (info));
1494 g_return_if_fail (mtime != NULL);
1496 if (attr_mtime == 0)
1498 attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1499 attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1502 value = g_file_info_create_value (info, attr_mtime);
1504 g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
1505 value = g_file_info_create_value (info, attr_mtime_usec);
1507 g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
1511 * g_file_info_set_symlink_target:
1512 * @info: a #GFileInfo.
1517 g_file_info_set_symlink_target (GFileInfo *info,
1518 const char *symlink_target)
1520 static guint32 attr = 0;
1521 GFileAttributeValue *value;
1523 g_return_if_fail (G_IS_FILE_INFO (info));
1524 g_return_if_fail (symlink_target != NULL);
1527 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET);
1529 value = g_file_info_create_value (info, attr);
1531 g_file_attribute_value_set_byte_string (value, symlink_target);
1535 * g_file_info_set_sort_order:
1536 * @info: a #GFileInfo.
1541 g_file_info_set_sort_order (GFileInfo *info,
1544 static guint32 attr = 0;
1545 GFileAttributeValue *value;
1547 g_return_if_fail (G_IS_FILE_INFO (info));
1550 attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SORT_ORDER);
1552 value = g_file_info_create_value (info, attr);
1554 g_file_attribute_value_set_int32 (value, sort_order);
1558 #define KILOBYTE_FACTOR 1024.0
1559 #define MEGABYTE_FACTOR (1024.0 * 1024.0)
1560 #define GIGABYTE_FACTOR (1024.0 * 1024.0 * 1024.0)
1563 g_format_file_size_for_display (goffset size)
1565 if (size < (goffset) KILOBYTE_FACTOR)
1566 return g_strdup_printf (dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes",(guint) size), (guint) size);
1569 gdouble displayed_size;
1571 if (size < (goffset) MEGABYTE_FACTOR)
1573 displayed_size = (gdouble) size / KILOBYTE_FACTOR;
1574 return g_strdup_printf (_("%.1f KB"), displayed_size);
1576 else if (size < (goffset) GIGABYTE_FACTOR)
1578 displayed_size = (gdouble) size / MEGABYTE_FACTOR;
1579 return g_strdup_printf (_("%.1f MB"), displayed_size);
1583 displayed_size = (gdouble) size / GIGABYTE_FACTOR;
1584 return g_strdup_printf (_("%.1f GB"), displayed_size);
1589 #define ON_STACK_MATCHERS 5
1596 struct _GFileAttributeMatcher {
1598 SubMatcher sub_matchers[ON_STACK_MATCHERS];
1599 GArray *more_sub_matchers;
1602 guint32 iterator_ns;
1608 matcher_add (GFileAttributeMatcher *matcher,
1609 guint id, guint mask)
1611 SubMatcher *sub_matchers;
1615 for (i = 0; i < ON_STACK_MATCHERS; i++)
1617 /* First empty spot, not found, use this */
1618 if (matcher->sub_matchers[i].id == 0)
1620 matcher->sub_matchers[i].id = id;
1621 matcher->sub_matchers[i].mask = mask;
1626 if (matcher->sub_matchers[i].id == id &&
1627 matcher->sub_matchers[i].mask == mask)
1631 if (matcher->more_sub_matchers == NULL)
1632 matcher->more_sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
1634 sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
1635 for (i = 0; i < matcher->more_sub_matchers->len; i++)
1638 if (sub_matchers[i].id == id &&
1639 sub_matchers[i].mask == mask)
1646 g_array_append_val (matcher->more_sub_matchers, s);
1650 * g_file_attribute_matcher_new
1653 * Returns: #GFileAttributeMatcher.
1655 GFileAttributeMatcher *
1656 g_file_attribute_matcher_new (const char *attributes)
1661 GFileAttributeMatcher *matcher;
1663 if (attributes == NULL || *attributes == '\0')
1666 matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
1669 split = g_strsplit (attributes, ",", -1);
1671 for (i = 0; split[i] != NULL; i++)
1673 if (strcmp (split[i], "*") == 0)
1674 matcher->all = TRUE;
1679 colon = strchr (split[i], ':');
1680 if (colon != NULL &&
1685 id = lookup_attribute (split[i]);
1693 id = lookup_namespace (split[i]) << NS_POS;
1694 mask = NS_MASK << NS_POS;
1697 matcher_add (matcher, id, mask);
1707 * g_file_attribute_matcher_ref:
1708 * @matcher: a #GFileAttributeMatcher.
1710 * Returns: a #GFileAttributeMatcher.
1712 GFileAttributeMatcher *
1713 g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
1715 g_return_val_if_fail (matcher != NULL, NULL);
1716 g_return_val_if_fail (matcher->ref > 0, NULL);
1718 g_atomic_int_inc (&matcher->ref);
1724 * g_file_attribute_matcher_unref:
1725 * @matcher: a #GFileAttributeMatcher.
1727 * Unreferences @matcher. If the reference count falls below 1,
1728 * the @matcher is automatically freed.
1732 g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
1734 g_return_if_fail (matcher != NULL);
1735 g_return_if_fail (matcher->ref > 0);
1737 if (g_atomic_int_dec_and_test (&matcher->ref))
1739 if (matcher->more_sub_matchers)
1740 g_array_free (matcher->more_sub_matchers, TRUE);
1747 * g_file_attribute_matcher_matches_only:
1748 * @matcher: a #GFileAttributeMatcher.
1754 g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
1755 const char *attribute)
1759 g_return_val_if_fail (matcher != NULL, FALSE);
1760 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
1765 id = lookup_attribute (attribute);
1767 if (matcher->sub_matchers[0].id != 0 &&
1768 matcher->sub_matchers[1].id == 0 &&
1769 matcher->sub_matchers[0].mask == 0xffffffff &&
1770 matcher->sub_matchers[0].id == id)
1777 matcher_matches_id (GFileAttributeMatcher *matcher,
1780 SubMatcher *sub_matchers;
1783 for (i = 0; i < ON_STACK_MATCHERS; i++)
1785 if (matcher->sub_matchers[i].id == 0)
1788 if (matcher->sub_matchers[i].id == (id & matcher->sub_matchers[i].mask))
1792 if (matcher->more_sub_matchers)
1794 sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
1795 for (i = 0; i < matcher->more_sub_matchers->len; i++)
1797 if (sub_matchers[i].id == (id & sub_matchers[i].mask))
1806 g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
1809 g_return_val_if_fail (matcher != NULL, FALSE);
1814 return matcher_matches_id (matcher, id);
1818 * g_file_attribute_matcher_matches:
1819 * @matcher: a #GFileAttributeMatcher.
1825 g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
1826 const char *attribute)
1828 g_return_val_if_fail (matcher != NULL, FALSE);
1829 g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
1834 return matcher_matches_id (matcher, lookup_attribute (attribute));
1837 /* return TRUE -> all */
1839 * g_file_attribute_matcher_enumerate_namespace:
1840 * @matcher: a #GFileAttributeMatcher.
1843 * Returns: %TRUE, %FALSE.
1846 g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
1849 SubMatcher *sub_matchers;
1853 g_return_val_if_fail (matcher != NULL, FALSE);
1854 g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
1859 ns_id = lookup_namespace (ns) << NS_POS;
1861 for (i = 0; i < ON_STACK_MATCHERS; i++)
1863 if (matcher->sub_matchers[i].id == ns_id)
1867 if (matcher->more_sub_matchers)
1869 sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
1870 for (i = 0; i < matcher->more_sub_matchers->len; i++)
1872 if (sub_matchers[i].id == ns_id)
1877 matcher->iterator_ns = ns_id;
1878 matcher->iterator_pos = 0;
1884 * g_file_attribute_matcher_enumerate_next:
1885 * @matcher: a #GFileAttributeMatcher.
1890 g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
1893 SubMatcher *sub_matcher;
1895 g_return_val_if_fail (matcher != NULL, NULL);
1899 i = matcher->iterator_pos++;
1901 if (i < ON_STACK_MATCHERS)
1903 if (matcher->sub_matchers[i].id == 0)
1906 sub_matcher = &matcher->sub_matchers[i];
1910 if (matcher->more_sub_matchers == NULL)
1913 i -= ON_STACK_MATCHERS;
1914 if (i < matcher->more_sub_matchers->len)
1915 sub_matcher = &g_array_index (matcher->more_sub_matchers, SubMatcher, i);
1920 if (sub_matcher->mask == 0xffffffff &&
1921 (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
1922 return get_attribute_for_id (sub_matcher->id);