chain up unconditionally in finalize() and dispose(). Also don't
[platform/upstream/glib.git] / gio / gfileinfo.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
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.
9  *
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.
14  *
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.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 /**
24  * SECTION:gfileinfo
25  * @short_description: File Information and Attributes
26  * @include: gio/gio.h
27  * @see_also: #GFile, <link linkend="gio-GFileAttribute">GFileAttribute</link>
28  * 
29  * Functionality for manipulating basic metadata for files. #GFileInfo
30  * implements methods for getting information that all files should 
31  * contain, and allows for manipulation of extended attributes. 
32  *
33  * See <link linkend="gio-GFileAttribute">GFileAttribute</link> for more
34  * information on how GIO handles file attributes.
35  *
36  * To obtain a #GFileInfo for a #GFile, use g_file_query_info() (or its 
37  * async variant). To obtain a #GFileInfo for a file input or output 
38  * stream, use g_file_input_stream_query_info() or 
39  * g_file_output_stream_query_info() (or their async variants).
40  *
41  * To change the actual attributes of a file, you should then set the 
42  * attribute in the #GFileInfo and call g_file_set_attributes_from_info() 
43  * or g_file_set_attributes_async() on a GFile.
44  *
45  * However, not all attributes can be changed in the file. For instance, 
46  * the actual size of a file cannot be changed via g_file_info_set_size(). 
47  * You may call g_file_query_settable_attributes() and 
48  * g_file_query_writable_namespaces() to discover the settable attributes 
49  * of a particular file at runtime.
50  *
51  * #GFileAttributeMatcher allows for searching through a #GFileInfo for 
52  * attributes.
53  **/
54
55 #include <config.h>
56
57 #include <string.h>
58
59 #include "gfileinfo.h"
60 #include "gfileattribute-priv.h"
61 #include "glibintl.h"
62
63 #include "gioalias.h"
64
65 /* We use this nasty thing, because NULL is a valid attribute matcher (matches nothing) */
66 #define NO_ATTRIBUTE_MASK ((GFileAttributeMatcher *)1)
67
68 typedef struct  {
69   guint32 attribute;
70   GFileAttributeValue value;
71 } GFileAttribute;
72
73 struct _GFileInfo
74 {
75   GObject parent_instance;
76
77   GArray *attributes;
78   GFileAttributeMatcher *mask;
79 };
80
81 struct _GFileInfoClass
82 {
83   GObjectClass parent_class;
84 };
85
86
87 static gboolean g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
88                                                      guint32 id);
89
90 G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT);
91
92 typedef struct {
93   guint32 id;
94   guint32 attribute_id_counter;
95 } NSInfo;
96
97 G_LOCK_DEFINE_STATIC (attribute_hash);
98 static int namespace_id_counter = 0;
99 static GHashTable *ns_hash = NULL;
100 static GHashTable *attribute_hash = NULL;
101 static char ***attributes = NULL;
102
103 /* Attribute ids are 32bit, we split it up like this:
104  * |------------|--------------------|
105  *   12 bit          20 bit       
106  *   namespace      attribute id    
107  *
108  * This way the attributes gets sorted in namespace order
109  */
110
111 #define NS_POS 20
112 #define NS_MASK ((guint32)((1<<12) - 1))
113 #define ID_POS 0
114 #define ID_MASK ((guint32)((1<<20) - 1))
115
116 #define GET_NS(_attr_id) \
117     (((guint32) (_attr_id) >> NS_POS) & NS_MASK)
118 #define GET_ID(_attr_id) \
119     (((guint32)(_attr_id) >> ID_POS) & ID_MASK)
120
121 #define MAKE_ATTR_ID(_ns, _id)                          \
122     ( ((((guint32) _ns) & NS_MASK) << NS_POS) |         \
123       ((((guint32) _id) & ID_MASK) << ID_POS) )
124
125 static NSInfo *
126 _lookup_namespace (const char *namespace)
127 {
128   NSInfo *ns_info;
129   
130   ns_info = g_hash_table_lookup (ns_hash, namespace);
131   if (ns_info == NULL)
132     {
133       ns_info = g_new0 (NSInfo, 1);
134       ns_info->id = ++namespace_id_counter;
135       g_hash_table_insert (ns_hash, g_strdup (namespace), ns_info);
136       attributes = g_realloc (attributes, (ns_info->id + 1) * sizeof (char **));
137       attributes[ns_info->id] = NULL;
138     }
139   return ns_info;
140 }
141
142 static guint32
143 lookup_namespace (const char *namespace)
144 {
145   NSInfo *ns_info;
146   guint32 id;
147   
148   G_LOCK (attribute_hash);
149   
150   if (attribute_hash == NULL)
151     {
152       ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
153       attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
154     }
155
156   ns_info = _lookup_namespace (namespace);
157   id = 0;
158   if (ns_info)
159     id = ns_info->id;
160   
161   G_UNLOCK (attribute_hash);
162
163   return id;
164 }
165
166 static char *
167 get_attribute_for_id (int attribute)
168 {
169   char *s;
170   G_LOCK (attribute_hash);
171   s = attributes[GET_NS(attribute)][GET_ID(attribute)];
172   G_UNLOCK (attribute_hash);
173   return s;
174 }
175
176 static guint32
177 lookup_attribute (const char *attribute)
178 {
179   guint32 attr_id, id;
180   char *ns;
181   const char *colon;
182   NSInfo *ns_info;
183   
184   G_LOCK (attribute_hash);
185   if (attribute_hash == NULL)
186     {
187       ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
188       attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
189     }
190
191   attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute));
192
193   if (attr_id != 0)
194     {
195       G_UNLOCK (attribute_hash);
196       return attr_id;
197     }
198
199   colon = strstr (attribute, "::");
200   if (colon)
201     ns = g_strndup (attribute, colon - attribute);
202   else
203     ns = g_strdup ("");
204
205   ns_info = _lookup_namespace (ns);
206   g_free (ns);
207
208   id = ++ns_info->attribute_id_counter;
209   attributes[ns_info->id] = g_realloc (attributes[ns_info->id], (id + 1) * sizeof (char *));
210   attributes[ns_info->id][id] = g_strdup (attribute);
211   
212   attr_id = MAKE_ATTR_ID (ns_info->id, id);
213
214   g_hash_table_insert (attribute_hash, attributes[ns_info->id][id], GUINT_TO_POINTER (attr_id));
215   
216   G_UNLOCK (attribute_hash);
217   
218   return attr_id;
219 }
220
221 static void
222 g_file_info_finalize (GObject *object)
223 {
224   GFileInfo *info;
225   int i;
226   GFileAttribute *attrs;
227
228   info = G_FILE_INFO (object);
229
230   attrs = (GFileAttribute *)info->attributes->data;
231   for (i = 0; i < info->attributes->len; i++)
232     _g_file_attribute_value_clear (&attrs[i].value);
233   g_array_free (info->attributes, TRUE);  
234
235   if (info->mask != NO_ATTRIBUTE_MASK)
236     g_file_attribute_matcher_unref (info->mask);
237
238   G_OBJECT_CLASS (g_file_info_parent_class)->finalize (object);
239 }
240
241 static void
242 g_file_info_class_init (GFileInfoClass *klass)
243 {
244   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
245   
246   gobject_class->finalize = g_file_info_finalize;
247 }
248
249 static void
250 g_file_info_init (GFileInfo *info)
251 {
252   info->mask = NO_ATTRIBUTE_MASK;
253   info->attributes = g_array_new (FALSE, FALSE,
254                                   sizeof (GFileAttribute));
255 }
256
257 /**
258  * g_file_info_new:
259  * 
260  * Creates a new file info structure.
261  * 
262  * Returns: a #GFileInfo.
263  **/
264 GFileInfo *
265 g_file_info_new (void)
266 {
267   return g_object_new (G_TYPE_FILE_INFO, NULL);
268 }
269
270 /**
271  * g_file_info_copy_into:
272  * @src_info: source to copy attributes from.
273  * @dest_info: destination to copy attributes to.
274  * 
275  * Copies all of the #GFileAttribute<!-- -->s from @src_info to @dest_info.
276  **/
277 void
278 g_file_info_copy_into (GFileInfo *src_info, 
279                        GFileInfo *dest_info)
280 {
281   GFileAttribute *source, *dest;
282   int i;
283
284   g_return_if_fail (G_IS_FILE_INFO (src_info));
285   g_return_if_fail (G_IS_FILE_INFO (dest_info));
286
287   dest = (GFileAttribute *)dest_info->attributes->data;
288   for (i = 0; i < dest_info->attributes->len; i++)
289     _g_file_attribute_value_clear (&dest[i].value);
290   
291   g_array_set_size (dest_info->attributes,
292                     src_info->attributes->len);
293
294   source = (GFileAttribute *)src_info->attributes->data;
295   dest = (GFileAttribute *)dest_info->attributes->data;
296   
297   for (i = 0; i < src_info->attributes->len; i++)
298     {
299       dest[i].attribute = source[i].attribute;
300       dest[i].value.type = G_FILE_ATTRIBUTE_TYPE_INVALID;
301       _g_file_attribute_value_set (&dest[i].value, &source[i].value);
302     }
303
304   if (src_info->mask == NO_ATTRIBUTE_MASK)
305     dest_info->mask = NO_ATTRIBUTE_MASK;
306   else
307     dest_info->mask = g_file_attribute_matcher_ref (src_info->mask);
308 }
309
310 /**
311  * g_file_info_dup:
312  * @other: a #GFileInfo.
313  * 
314  * Duplicates a file info structure.
315  * 
316  * Returns: a duplicate #GFileInfo of @other.
317  **/
318 GFileInfo *
319 g_file_info_dup (GFileInfo *other)
320 {
321   GFileInfo *new;
322   
323   g_return_val_if_fail (G_IS_FILE_INFO (other), NULL);
324   
325   new = g_file_info_new ();
326   g_file_info_copy_into (other, new);
327   return new;
328 }
329
330 /**
331  * g_file_info_set_attribute_mask:
332  * @info: a #GFileInfo.
333  * @mask: a #GFileAttributeMatcher.
334  *
335  * Sets @mask on @info to match specific attribute types.
336  **/
337 void
338 g_file_info_set_attribute_mask (GFileInfo             *info,
339                                 GFileAttributeMatcher *mask)
340 {
341   GFileAttribute *attr;
342   int i;
343   
344   g_return_if_fail (G_IS_FILE_INFO (info));
345   
346   if (mask != info->mask)
347     {
348       if (info->mask != NO_ATTRIBUTE_MASK)
349         g_file_attribute_matcher_unref (info->mask);
350       info->mask = g_file_attribute_matcher_ref (mask);
351
352       /* Remove non-matching attributes */
353       for (i = 0; i < info->attributes->len; i++)
354         {
355           attr = &g_array_index (info->attributes, GFileAttribute, i);
356           if (!g_file_attribute_matcher_matches_id (mask,
357                                                     attr->attribute))
358             {
359               _g_file_attribute_value_clear (&attr->value);
360               g_array_remove_index (info->attributes, i);
361               i--;
362             }
363         }
364     }
365 }
366
367 /**
368  * g_file_info_unset_attribute_mask:
369  * @info: #GFileInfo.
370  * 
371  * Unsets a mask set by g_file_info_set_attribute_mask(), if one
372  * is set.
373  **/
374 void
375 g_file_info_unset_attribute_mask (GFileInfo *info)
376 {
377   g_return_if_fail (G_IS_FILE_INFO (info));
378
379   if (info->mask != NO_ATTRIBUTE_MASK)
380     g_file_attribute_matcher_unref (info->mask);
381   info->mask = NO_ATTRIBUTE_MASK;
382 }
383
384 /**
385  * g_file_info_clear_status:
386  * @info: a #GFileInfo.
387  *
388  * Clears the status information from @info.
389  **/
390 void
391 g_file_info_clear_status (GFileInfo  *info)
392 {
393   GFileAttribute *attrs;
394   int i;
395   
396   g_return_if_fail (G_IS_FILE_INFO (info));
397
398   attrs = (GFileAttribute *)info->attributes->data;
399   for (i = 0; i < info->attributes->len; i++)
400     attrs[i].value.status = G_FILE_ATTRIBUTE_STATUS_UNSET;
401 }
402
403 static int
404 g_file_info_find_place (GFileInfo  *info,
405                         guint32     attribute)
406 {
407   int min, max, med;
408   GFileAttribute *attrs;
409   /* Binary search for the place where attribute would be, if its
410      in the array */
411
412   min = 0;
413   max = info->attributes->len;
414
415   attrs = (GFileAttribute *)info->attributes->data;
416
417   while (min < max)
418     {
419       med = min + (max - min) / 2;
420       if (attrs[med].attribute == attribute)
421         {
422           min = med;
423           break;
424         }
425       else if (attrs[med].attribute < attribute)
426         min = med + 1;
427       else /* attrs[med].attribute > attribute */
428         max = med;
429     }
430
431   return min;
432 }
433
434 static GFileAttributeValue *
435 g_file_info_find_value (GFileInfo *info,
436                         guint32    attr_id)
437 {
438   GFileAttribute *attrs;
439   int i;
440
441   i = g_file_info_find_place (info, attr_id);
442   attrs = (GFileAttribute *)info->attributes->data;
443   if (i < info->attributes->len &&
444       attrs[i].attribute == attr_id)
445     return &attrs[i].value;
446   
447   return NULL;
448 }
449
450 static GFileAttributeValue *
451 g_file_info_find_value_by_name (GFileInfo  *info,
452                                 const char *attribute)
453 {
454   guint32 attr_id;
455
456   attr_id = lookup_attribute (attribute);
457   return g_file_info_find_value (info, attr_id);
458 }
459
460 /**
461  * g_file_info_has_attribute:
462  * @info: a #GFileInfo.
463  * @attribute: a file attribute key.
464  * 
465  * Checks if a file info structure has an attribute named @attribute.
466  * 
467  * Returns: %TRUE if @Ginfo has an attribute named @attribute, 
468  *     %FALSE otherwise.
469  **/
470 gboolean
471 g_file_info_has_attribute (GFileInfo  *info,
472                            const char *attribute)
473 {
474   GFileAttributeValue *value;
475
476   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
477   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
478
479   value = g_file_info_find_value_by_name (info, attribute);
480   return value != NULL;
481 }
482
483 /**
484  * g_file_info_list_attributes:
485  * @info: a #GFileInfo.
486  * @name_space: a file attribute key's namespace.
487  * 
488  * Lists the file info structure's attributes.
489  * 
490  * Returns: a null-terminated array of strings of all of the 
491  * possible attribute types for the given @name_space, or 
492  * %NULL on error.
493  **/
494 char **
495 g_file_info_list_attributes (GFileInfo  *info,
496                              const char *name_space)
497 {
498   GPtrArray *names;
499   GFileAttribute *attrs;
500   guint32 attribute;
501   guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0;
502   int i;
503  
504   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
505
506   names = g_ptr_array_new ();
507   attrs = (GFileAttribute *)info->attributes->data;
508   for (i = 0; i < info->attributes->len; i++)
509     {
510       attribute = attrs[i].attribute;
511       if (ns_id == 0 || GET_NS (attribute) == ns_id)
512         g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute)));
513     }
514
515   /* NULL terminate */
516   g_ptr_array_add (names, NULL);
517   
518   return (char **)g_ptr_array_free (names, FALSE);
519 }
520
521 /**
522  * g_file_info_get_attribute_type:
523  * @info: a #GFileInfo.
524  * @attribute: a file attribute key.
525  * 
526  * Gets the attribute type for an attribute key.
527  * 
528  * Returns: a #GFileAttributeType for the given @attribute, or 
529  * %G_FILE_ATTRIBUTE_TYPE_INVALID if the key is invalid.
530  **/
531 GFileAttributeType
532 g_file_info_get_attribute_type (GFileInfo  *info,
533                                 const char *attribute)
534 {
535   GFileAttributeValue *value;
536   
537   g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_ATTRIBUTE_TYPE_INVALID);
538   g_return_val_if_fail (attribute != NULL && *attribute != '\0', G_FILE_ATTRIBUTE_TYPE_INVALID);
539
540   value = g_file_info_find_value_by_name (info, attribute);
541   if (value)
542     return value->type;
543   else
544     return G_FILE_ATTRIBUTE_TYPE_INVALID;
545 }
546
547 /**
548  * g_file_info_remove_attribute:
549  * @info: a #GFileInfo.
550  * @attribute: a file attribute key.
551  * 
552  * Removes all cases of @attribute from @info if it exists.
553  **/
554 void
555 g_file_info_remove_attribute (GFileInfo  *info,
556                               const char *attribute)
557 {
558   guint32 attr_id;
559   GFileAttribute *attrs;
560   int i;
561
562   g_return_if_fail (G_IS_FILE_INFO (info));
563   g_return_if_fail (attribute != NULL && *attribute != '\0');
564
565   attr_id = lookup_attribute (attribute);
566   
567   i = g_file_info_find_place (info, attr_id);
568   attrs = (GFileAttribute *)info->attributes->data;
569   if (i < info->attributes->len &&
570       attrs[i].attribute == attr_id)
571     {
572       _g_file_attribute_value_clear (&attrs[i].value);
573       g_array_remove_index (info->attributes, i);
574     }
575 }
576
577 /**
578  * g_file_info_get_attribute_data:
579  * @info: a #GFileInfo
580  * @attribute: a file attribute key
581  * @type: return location for the attribute type, or %NULL
582  * @value_pp: return location for the attribute value, or %NULL
583  * @status: return location for the attribute status, or %NULL
584  *
585  * Gets the attribute type, value and status for an attribute key.
586  *
587  * Returns: %TRUE if @info has an attribute named @attribute, 
588  *      %FALSE otherwise.
589  */
590 gboolean
591 g_file_info_get_attribute_data (GFileInfo            *info,
592                                 const char           *attribute,
593                                 GFileAttributeType   *type,
594                                 gpointer             *value_pp,
595                                 GFileAttributeStatus *status)
596 {
597   GFileAttributeValue *value;
598
599   value = g_file_info_find_value_by_name (info, attribute);
600   if (value == NULL)
601     return FALSE;
602
603   if (status)
604     *status = value->status;
605
606   if (type)
607     *type = value->type;
608
609   if (value_pp)
610     *value_pp = _g_file_attribute_value_peek_as_pointer (value);
611   
612   return TRUE;
613 }
614
615 /** 
616  * g_file_info_get_attribute_status:
617  * @info: a #GFileInfo
618  * @attribute: a file attribute key
619  *
620  * Gets the attribute status for an attribute key.
621  *
622  * Returns: a #GFileAttributeStatus for the given @attribute, or 
623  *    %G_FILE_ATTRIBUTE_STATUS_UNSET if the key is invalid.
624  *
625  */
626 GFileAttributeStatus
627 g_file_info_get_attribute_status (GFileInfo  *info,
628                                   const char *attribute)
629 {
630   GFileAttributeValue *val;
631   
632   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
633   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
634
635   val = g_file_info_find_value_by_name (info, attribute);
636   if (val)
637     return val->status;
638
639   return G_FILE_ATTRIBUTE_STATUS_UNSET;
640 }
641
642
643 GFileAttributeValue *
644 _g_file_info_get_attribute_value (GFileInfo  *info,
645                                   const char *attribute)
646   
647 {
648   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
649   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
650
651   return g_file_info_find_value_by_name (info, attribute);
652 }
653
654 /**
655  * g_file_info_get_attribute_as_string:
656  * @info: a #GFileInfo.
657  * @attribute: a file attribute key.
658  * 
659  * Gets the value of a attribute, formated as a string.
660  * This escapes things as needed to make the string valid
661  * utf8.
662  * 
663  * Returns: a UTF-8 string associated with the given @attribute.
664  *    When you're done with the string it must be freed with g_free().
665  **/
666 char *
667 g_file_info_get_attribute_as_string (GFileInfo  *info,
668                                      const char *attribute)
669 {
670   GFileAttributeValue *val;
671   val = _g_file_info_get_attribute_value (info, attribute);
672   if (val) 
673     return _g_file_attribute_value_as_string (val);
674   return NULL;
675 }
676
677
678 /**
679  * g_file_info_get_attribute_object:
680  * @info: a #GFileInfo.
681  * @attribute: a file attribute key.
682  * 
683  * Gets the value of a #GObject attribute. If the attribute does 
684  * not contain a #GObject, %NULL will be returned.
685  * 
686  * Returns: a #GObject associated with the given @attribute, or
687  * %NULL otherwise.
688  **/
689 GObject *
690 g_file_info_get_attribute_object (GFileInfo  *info,
691                                   const char *attribute)
692 {
693   GFileAttributeValue *value;
694   
695   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
696   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
697
698   value = g_file_info_find_value_by_name (info, attribute);
699   return _g_file_attribute_value_get_object (value);
700 }
701
702 /**
703  * g_file_info_get_attribute_string:
704  * @info: a #GFileInfo.
705  * @attribute: a file attribute key.
706  * 
707  * Gets the value of a string attribute. If the attribute does 
708  * not contain a string, %NULL will be returned.
709  * 
710  * Returns: the contents of the @attribute value as a string, or 
711  * %NULL otherwise.
712  **/
713 const char *
714 g_file_info_get_attribute_string (GFileInfo  *info,
715                                   const char *attribute)
716 {
717   GFileAttributeValue *value;
718   
719   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
720   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
721
722   value = g_file_info_find_value_by_name (info, attribute);
723   return _g_file_attribute_value_get_string (value);
724 }
725
726 /**
727  * g_file_info_get_attribute_byte_string:
728  * @info: a #GFileInfo.
729  * @attribute: a file attribute key.
730  * 
731  * Gets the value of a byte string attribute. If the attribute does 
732  * not contain a byte string, %NULL will be returned.
733  * 
734  * Returns: the contents of the @attribute value as a byte string, or 
735  * %NULL otherwise.
736  **/
737 const char *
738 g_file_info_get_attribute_byte_string (GFileInfo  *info,
739                                        const char *attribute)
740 {
741   GFileAttributeValue *value;
742   
743   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
744   g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
745
746   value = g_file_info_find_value_by_name (info, attribute);
747   return _g_file_attribute_value_get_byte_string (value);
748 }
749
750 /**
751  * g_file_info_get_attribute_boolean:
752  * @info: a #GFileInfo.
753  * @attribute: a file attribute key.
754  * 
755  * Gets the value of a boolean attribute. If the attribute does not
756  * contain a boolean value, %FALSE will be returned.
757  * 
758  * Returns: the boolean value contained within the attribute. 
759  **/
760 gboolean
761 g_file_info_get_attribute_boolean (GFileInfo  *info,
762                                    const char *attribute)
763 {
764   GFileAttributeValue *value;
765   
766   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
767   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
768
769   value = g_file_info_find_value_by_name (info, attribute);
770   return _g_file_attribute_value_get_boolean (value);
771 }
772
773 /**
774  * g_file_info_get_attribute_uint32:
775  * @info: a #GFileInfo.
776  * @attribute: a file attribute key.
777  * 
778  * Gets an unsigned 32-bit integer contained within the attribute. If the 
779  * attribute does not contain an unsigned 32-bit integer, or is invalid, 
780  * 0 will be returned.
781  * 
782  * Returns: an unsigned 32-bit integer from the attribute. 
783  **/
784 guint32
785 g_file_info_get_attribute_uint32 (GFileInfo  *info,
786                                   const char *attribute)
787 {
788   GFileAttributeValue *value;
789   
790   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
791   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
792
793   value = g_file_info_find_value_by_name (info, attribute);
794   return _g_file_attribute_value_get_uint32 (value);
795 }
796
797 /**
798  * g_file_info_get_attribute_int32:
799  * @info: a #GFileInfo.
800  * @attribute: a file attribute key.
801  * 
802  * Gets a signed 32-bit integer contained within the attribute. If the 
803  * attribute does not contain a signed 32-bit integer, or is invalid, 
804  * 0 will be returned.
805  * 
806  * Returns: a signed 32-bit integer from the attribute.
807  **/
808 gint32
809 g_file_info_get_attribute_int32 (GFileInfo  *info,
810                                  const char *attribute)
811 {
812   GFileAttributeValue *value;
813
814   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
815   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
816
817   value = g_file_info_find_value_by_name (info, attribute);
818   return _g_file_attribute_value_get_int32 (value);
819 }
820
821 /**
822  * g_file_info_get_attribute_uint64:
823  * @info: a #GFileInfo.
824  * @attribute: a file attribute key.
825  * 
826  * Gets a unsigned 64-bit integer contained within the attribute. If the 
827  * attribute does not contain an unsigned 64-bit integer, or is invalid, 
828  * 0 will be returned.
829  * 
830  * Returns: a unsigned 64-bit integer from the attribute. 
831  **/
832 guint64
833 g_file_info_get_attribute_uint64 (GFileInfo  *info,
834                                   const char *attribute)
835 {
836   GFileAttributeValue *value;
837
838   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
839   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
840
841   value = g_file_info_find_value_by_name (info, attribute);
842   return _g_file_attribute_value_get_uint64 (value);
843 }
844
845 /**
846  * g_file_info_get_attribute_int64:
847  * @info: a #GFileInfo.
848  * @attribute: a file attribute key.
849  * 
850  * Gets a signed 64-bit integer contained within the attribute. If the 
851  * attribute does not contain an signed 64-bit integer, or is invalid, 
852  * 0 will be returned.
853  * 
854  * Returns: a signed 64-bit integer from the attribute. 
855  **/
856 gint64
857 g_file_info_get_attribute_int64  (GFileInfo  *info,
858                                   const char *attribute)
859 {
860   GFileAttributeValue *value;
861
862   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
863   g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
864
865   value = g_file_info_find_value_by_name (info, attribute);
866   return _g_file_attribute_value_get_int64 (value);
867 }
868
869 static GFileAttributeValue *
870 g_file_info_create_value (GFileInfo *info,
871                           guint32 attr_id)
872 {
873   GFileAttribute *attrs;
874   int i;
875
876   if (info->mask != NO_ATTRIBUTE_MASK &&
877       !g_file_attribute_matcher_matches_id (info->mask, attr_id))
878     return NULL;
879   
880   i = g_file_info_find_place (info, attr_id);
881   
882   attrs = (GFileAttribute *)info->attributes->data;
883   if (i < info->attributes->len &&
884       attrs[i].attribute == attr_id)
885     return &attrs[i].value;
886   else
887     {
888       GFileAttribute attr = { 0 };
889       attr.attribute = attr_id;
890       g_array_insert_val (info->attributes, i, attr);
891
892       attrs = (GFileAttribute *)info->attributes->data;
893       return &attrs[i].value;
894     }
895 }
896
897 static GFileAttributeValue *
898 g_file_info_create_value_by_name (GFileInfo *info,
899                                   const char *attribute)
900 {
901   guint32 attr_id;
902
903   attr_id = lookup_attribute (attribute);
904
905   return g_file_info_create_value (info, attr_id);
906 }
907
908 /**
909  * g_file_info_set_attribute:
910  * @info: a #GFileInfo.
911  * @attribute: a file attribute key.
912  * @type: a #GFileAttributeType
913  * @value_p: pointer to the value
914  * 
915  * Sets the @attribute to contain the given value, if possible.
916  **/
917 void
918 g_file_info_set_attribute (GFileInfo                 *info,
919                            const char                *attribute,
920                            GFileAttributeType         type,
921                            gpointer                   value_p)
922 {
923   GFileAttributeValue *value;
924
925   g_return_if_fail (G_IS_FILE_INFO (info));
926   g_return_if_fail (attribute != NULL && *attribute != '\0');
927
928   value = g_file_info_create_value_by_name (info, attribute);
929
930   if (value)
931     _g_file_attribute_value_set_from_pointer (value, type, value_p, TRUE);
932 }
933
934 /**
935  * g_file_info_set_attribute_object:
936  * @info: a #GFileInfo.
937  * @attribute: a file attribute key.
938  * @attr_value: a #GObject.
939  * 
940  * Sets the @attribute to contain the given @attr_value, 
941  * if possible.
942  **/
943 void
944 g_file_info_set_attribute_object (GFileInfo  *info,
945                                   const char *attribute,
946                                   GObject    *attr_value)
947 {
948   GFileAttributeValue *value;
949
950   g_return_if_fail (G_IS_FILE_INFO (info));
951   g_return_if_fail (attribute != NULL && *attribute != '\0');
952   g_return_if_fail (G_IS_OBJECT (attr_value));
953
954   value = g_file_info_create_value_by_name (info, attribute);
955   if (value)
956     _g_file_attribute_value_set_object (value, attr_value);
957 }
958
959 /**
960  * g_file_info_set_attribute_string:
961  * @info: a #GFileInfo.
962  * @attribute: a file attribute key.
963  * @attr_value: a string.
964  * 
965  * Sets the @attribute to contain the given @attr_value, 
966  * if possible.
967  **/
968 void
969 g_file_info_set_attribute_string (GFileInfo  *info,
970                                   const char *attribute,
971                                   const char *attr_value)
972 {
973   GFileAttributeValue *value;
974   
975   g_return_if_fail (G_IS_FILE_INFO (info));
976   g_return_if_fail (attribute != NULL && *attribute != '\0');
977   g_return_if_fail (attr_value != NULL);
978
979   value = g_file_info_create_value_by_name (info, attribute);
980   if (value)
981     _g_file_attribute_value_set_string (value, attr_value);
982 }
983
984 /**
985  * g_file_info_set_attribute_byte_string:
986  * @info: a #GFileInfo.
987  * @attribute: a file attribute key.
988  * @attr_value: a byte string.
989  * 
990  * Sets the @attribute to contain the given @attr_value, 
991  * if possible.
992  **/
993 void
994 g_file_info_set_attribute_byte_string (GFileInfo  *info,
995                                        const char *attribute,
996                                        const char *attr_value)
997 {
998   GFileAttributeValue *value;
999
1000   g_return_if_fail (G_IS_FILE_INFO (info));
1001   g_return_if_fail (attribute != NULL && *attribute != '\0');
1002   g_return_if_fail (attr_value != NULL);
1003
1004   value = g_file_info_create_value_by_name (info, attribute);
1005   if (value)
1006     _g_file_attribute_value_set_byte_string (value, attr_value);
1007 }
1008
1009 /**
1010  * g_file_info_set_attribute_boolean:
1011  * @info: a #GFileInfo.
1012  * @attribute: a file attribute key.
1013  * @attr_value: a boolean value.
1014  * 
1015  * Sets the @attribute to contain the given @attr_value, 
1016  * if possible.
1017  **/
1018 void
1019 g_file_info_set_attribute_boolean (GFileInfo  *info,
1020                                    const char *attribute,
1021                                    gboolean    attr_value)
1022 {
1023   GFileAttributeValue *value;
1024
1025   g_return_if_fail (G_IS_FILE_INFO (info));
1026   g_return_if_fail (attribute != NULL && *attribute != '\0');
1027
1028   value = g_file_info_create_value_by_name (info, attribute);
1029   if (value)
1030     _g_file_attribute_value_set_boolean (value, attr_value);
1031 }
1032
1033 /**
1034  * g_file_info_set_attribute_uint32:
1035  * @info: a #GFileInfo.
1036  * @attribute: a file attribute key.
1037  * @attr_value: an unsigned 32-bit integer.
1038  * 
1039  * Sets the @attribute to contain the given @attr_value, 
1040  * if possible.
1041  **/
1042 void
1043 g_file_info_set_attribute_uint32 (GFileInfo  *info,
1044                                   const char *attribute,
1045                                   guint32     attr_value)
1046 {
1047   GFileAttributeValue *value;
1048
1049   g_return_if_fail (G_IS_FILE_INFO (info));
1050   g_return_if_fail (attribute != NULL && *attribute != '\0');
1051
1052   value = g_file_info_create_value_by_name (info, attribute);
1053   if (value)
1054     _g_file_attribute_value_set_uint32 (value, attr_value);
1055 }
1056
1057
1058 /**
1059  * g_file_info_set_attribute_int32:
1060  * @info: a #GFileInfo.
1061  * @attribute: a file attribute key.
1062  * @attr_value: a signed 32-bit integer
1063  * 
1064  * Sets the @attribute to contain the given @attr_value, 
1065  * if possible.
1066  **/
1067 void
1068 g_file_info_set_attribute_int32 (GFileInfo  *info,
1069                                  const char *attribute,
1070                                  gint32      attr_value)
1071 {
1072   GFileAttributeValue *value;
1073  
1074   g_return_if_fail (G_IS_FILE_INFO (info));
1075   g_return_if_fail (attribute != NULL && *attribute != '\0');
1076
1077   value = g_file_info_create_value_by_name (info, attribute);
1078   if (value)
1079     _g_file_attribute_value_set_int32 (value, attr_value);
1080 }
1081
1082 /**
1083  * g_file_info_set_attribute_uint64:
1084  * @info: a #GFileInfo.
1085  * @attribute: a file attribute key.
1086  * @attr_value: an unsigned 64-bit integer.
1087  * 
1088  * Sets the @attribute to contain the given @attr_value, 
1089  * if possible.
1090  **/
1091 void
1092 g_file_info_set_attribute_uint64 (GFileInfo  *info,
1093                                   const char *attribute,
1094                                   guint64     attr_value)
1095 {
1096   GFileAttributeValue *value;
1097
1098   g_return_if_fail (G_IS_FILE_INFO (info));
1099   g_return_if_fail (attribute != NULL && *attribute != '\0');
1100
1101   value = g_file_info_create_value_by_name (info, attribute);
1102   if (value)
1103     _g_file_attribute_value_set_uint64 (value, attr_value);
1104 }
1105
1106 /**
1107  * g_file_info_set_attribute_int64:
1108  * @info: a #GFileInfo.
1109  * @attribute: attribute name to set.
1110  * @attr_value: int64 value to set attribute to.
1111  * 
1112  * Sets the @attribute to contain the given @attr_value, 
1113  * if possible.
1114  * 
1115  **/
1116 void
1117 g_file_info_set_attribute_int64  (GFileInfo  *info,
1118                                   const char *attribute,
1119                                   gint64      attr_value)
1120 {
1121   GFileAttributeValue *value;
1122
1123   g_return_if_fail (G_IS_FILE_INFO (info));
1124   g_return_if_fail (attribute != NULL && *attribute != '\0');
1125
1126   value = g_file_info_create_value_by_name (info, attribute);
1127   if (value)
1128     _g_file_attribute_value_set_int64 (value, attr_value);
1129 }
1130
1131 /* Helper getters */
1132 /**
1133  * g_file_info_get_file_type:
1134  * @info: a #GFileInfo.
1135  * 
1136  * Gets a file's type (whether it is a regular file, symlink, etc). 
1137  * This is different from the file's content type, see g_file_info_get_content_type().
1138  * 
1139  * Returns: a #GFileType for the given file.
1140  **/
1141 GFileType
1142 g_file_info_get_file_type (GFileInfo *info)
1143 {
1144   static guint32 attr = 0;
1145   GFileAttributeValue *value;
1146
1147   g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_TYPE_UNKNOWN);
1148   
1149   if (attr == 0)
1150     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
1151   
1152   value = g_file_info_find_value (info, attr);
1153   return (GFileType)_g_file_attribute_value_get_uint32 (value);
1154 }
1155
1156 /**
1157  * g_file_info_get_is_hidden:
1158  * @info: a #GFileInfo.
1159  * 
1160  * Checks if a file is hidden.
1161  * 
1162  * Returns: %TRUE if the file is a hidden file, %FALSE otherwise.
1163  **/
1164 gboolean
1165 g_file_info_get_is_hidden (GFileInfo *info)
1166 {
1167   static guint32 attr = 0;
1168   GFileAttributeValue *value;
1169   
1170   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1171   
1172   if (attr == 0)
1173     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
1174   
1175   value = g_file_info_find_value (info, attr);
1176   return (GFileType)_g_file_attribute_value_get_boolean (value);
1177 }
1178
1179 /**
1180  * g_file_info_get_is_backup:
1181  * @info: a #GFileInfo.
1182  * 
1183  * Checks if a file is a backup file.
1184  * 
1185  * Returns: %TRUE if file is a backup file, %FALSE otherwise.
1186  **/
1187 gboolean
1188 g_file_info_get_is_backup (GFileInfo *info)
1189 {
1190   static guint32 attr = 0;
1191   GFileAttributeValue *value;
1192   
1193   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1194   
1195   if (attr == 0)
1196     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP);
1197   
1198   value = g_file_info_find_value (info, attr);
1199   return (GFileType)_g_file_attribute_value_get_boolean (value);
1200 }
1201
1202 /**
1203  * g_file_info_get_is_symlink:
1204  * @info: a #GFileInfo.
1205  * 
1206  * Checks if a file is a symlink.
1207  * 
1208  * Returns: %TRUE if the given @info is a symlink.
1209  **/
1210 gboolean
1211 g_file_info_get_is_symlink (GFileInfo *info)
1212 {
1213   static guint32 attr = 0;
1214   GFileAttributeValue *value;
1215   
1216   g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1217   
1218   if (attr == 0)
1219     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
1220   
1221   value = g_file_info_find_value (info, attr);
1222   return (GFileType)_g_file_attribute_value_get_boolean (value);
1223 }
1224
1225 /**
1226  * g_file_info_get_name:
1227  * @info: a #GFileInfo.
1228  * 
1229  * Gets the name for a file.
1230  * 
1231  * Returns: a string containing the file name.
1232  **/
1233 const char *
1234 g_file_info_get_name (GFileInfo *info)
1235 {
1236   static guint32 attr = 0;
1237   GFileAttributeValue *value;
1238   
1239   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1240   
1241   if (attr == 0)
1242     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
1243   
1244   value = g_file_info_find_value (info, attr);
1245   return _g_file_attribute_value_get_byte_string (value);
1246 }
1247
1248 /**
1249  * g_file_info_get_display_name:
1250  * @info: a #GFileInfo.
1251  * 
1252  * Gets a display name for a file.
1253  * 
1254  * Returns: a string containing the display name.
1255  **/
1256 const char *
1257 g_file_info_get_display_name (GFileInfo *info)
1258 {
1259   static guint32 attr = 0;
1260   GFileAttributeValue *value;
1261   
1262   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1263   
1264   if (attr == 0)
1265     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
1266   
1267   value = g_file_info_find_value (info, attr);
1268   return _g_file_attribute_value_get_string (value);
1269 }
1270
1271 /**
1272  * g_file_info_get_edit_name:
1273  * @info: a #GFileInfo.
1274  * 
1275  * Gets the edit name for a file.
1276  * 
1277  * Returns: a string containing the edit name.
1278  **/
1279 const char *
1280 g_file_info_get_edit_name (GFileInfo *info)
1281 {
1282   static guint32 attr = 0;
1283   GFileAttributeValue *value;
1284   
1285   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1286   
1287   if (attr == 0)
1288     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
1289   
1290   value = g_file_info_find_value (info, attr);
1291   return _g_file_attribute_value_get_string (value);
1292 }
1293
1294 /**
1295  * g_file_info_get_icon:
1296  * @info: a #GFileInfo.
1297  * 
1298  * Gets the icon for a file.
1299  * 
1300  * Returns: #GIcon for the given @info.
1301  **/
1302 GIcon *
1303 g_file_info_get_icon (GFileInfo *info)
1304 {
1305   static guint32 attr = 0;
1306   GFileAttributeValue *value;
1307   GObject *obj;
1308   
1309   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1310   
1311   if (attr == 0)
1312     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
1313   
1314   value = g_file_info_find_value (info, attr);
1315   obj = _g_file_attribute_value_get_object (value);
1316   if (G_IS_ICON (obj))
1317     return G_ICON (obj);
1318   return NULL;
1319 }
1320
1321 /**
1322  * g_file_info_get_content_type:
1323  * @info: a #GFileInfo.
1324  * 
1325  * Gets the file's content type.
1326  * 
1327  * Returns: a string containing the file's content type.s
1328  **/
1329 const char *
1330 g_file_info_get_content_type (GFileInfo *info)
1331 {
1332   static guint32 attr = 0;
1333   GFileAttributeValue *value;
1334   
1335   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1336   
1337   if (attr == 0)
1338     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1339   
1340   value = g_file_info_find_value (info, attr);
1341   return _g_file_attribute_value_get_string (value);
1342 }
1343
1344 /**
1345  * g_file_info_get_size:
1346  * @info: a #GFileInfo.
1347  * 
1348  * Gets the file's size.
1349  * 
1350  * Returns: a #goffset containing the file's size. 
1351  **/
1352 goffset
1353 g_file_info_get_size (GFileInfo *info)
1354 {
1355   static guint32 attr = 0;
1356   GFileAttributeValue *value;
1357  
1358   g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1359   
1360   if (attr == 0)
1361     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
1362   
1363   value = g_file_info_find_value (info, attr);
1364   return (goffset) _g_file_attribute_value_get_uint64 (value);
1365 }
1366
1367 /**
1368  * g_file_info_get_modification_time:
1369  * @info: a #GFileInfo.
1370  * @result: a #GTimeVal.
1371  * 
1372  * Gets the modification time of the current @info and sets it
1373  * in @result.
1374  **/
1375 void
1376 g_file_info_get_modification_time (GFileInfo *info,
1377                                    GTimeVal  *result)
1378 {
1379   static guint32 attr_mtime = 0, attr_mtime_usec;
1380   GFileAttributeValue *value;
1381
1382   g_return_if_fail (G_IS_FILE_INFO (info));
1383   g_return_if_fail (result != NULL);
1384   
1385   if (attr_mtime == 0)
1386     {
1387       attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1388       attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1389     }
1390   
1391   value = g_file_info_find_value (info, attr_mtime);
1392   result->tv_sec = _g_file_attribute_value_get_uint64 (value);
1393   value = g_file_info_find_value (info, attr_mtime_usec);
1394   result->tv_usec = _g_file_attribute_value_get_uint32 (value);
1395 }
1396
1397 /**
1398  * g_file_info_get_symlink_target:
1399  * @info: a #GFileInfo.
1400  * 
1401  * Gets the symlink target for a given #GFileInfo.
1402  * 
1403  * Returns: a string containing the symlink target.
1404  **/
1405 const char *
1406 g_file_info_get_symlink_target (GFileInfo *info)
1407 {
1408   static guint32 attr = 0;
1409   GFileAttributeValue *value;
1410   
1411   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1412   
1413   if (attr == 0)
1414     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
1415   
1416   value = g_file_info_find_value (info, attr);
1417   return _g_file_attribute_value_get_byte_string (value);
1418 }
1419
1420 /**
1421  * g_file_info_get_etag:
1422  * @info: a #GFileInfo.
1423  * 
1424  * Gets the <link linkend="gfile-etag">entity tag</link> for a given 
1425  * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
1426  * 
1427  * Returns: a string containing the value of the "etag:value" attribute.
1428  **/
1429 const char *
1430 g_file_info_get_etag (GFileInfo *info)
1431 {
1432   static guint32 attr = 0;
1433   GFileAttributeValue *value;
1434   
1435   g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1436   
1437   if (attr == 0)
1438     attr = lookup_attribute (G_FILE_ATTRIBUTE_ETAG_VALUE);
1439   
1440   value = g_file_info_find_value (info, attr);
1441   return _g_file_attribute_value_get_string (value);
1442 }
1443
1444 /**
1445  * g_file_info_get_sort_order:
1446  * @info: a #GFileInfo.
1447  * 
1448  * Gets the value of the sort_order attribute from the #GFileInfo.
1449  * See %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
1450  * 
1451  * Returns: a #gint32 containing the value of the "standard::sort_order" attribute.
1452  **/
1453 gint32
1454 g_file_info_get_sort_order (GFileInfo *info)
1455 {
1456   static guint32 attr = 0;
1457   GFileAttributeValue *value;
1458   
1459   g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1460   
1461   if (attr == 0)
1462     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
1463   
1464   value = g_file_info_find_value (info, attr);
1465   return _g_file_attribute_value_get_int32 (value);
1466 }
1467
1468 /* Helper setters: */
1469 /**
1470  * g_file_info_set_file_type:
1471  * @info: a #GFileInfo.
1472  * @type: a #GFileType.
1473  * 
1474  * Sets the file type in a #GFileInfo to @type.
1475  * See %G_FILE_ATTRIBUTE_STANDARD_TYPE.
1476  **/
1477 void
1478 g_file_info_set_file_type (GFileInfo *info,
1479                            GFileType  type)
1480 {
1481   static guint32 attr = 0;
1482   GFileAttributeValue *value;
1483   
1484   g_return_if_fail (G_IS_FILE_INFO (info));
1485   
1486   if (attr == 0)
1487     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
1488   
1489   value = g_file_info_create_value (info, attr);
1490   if (value)
1491     _g_file_attribute_value_set_uint32 (value, type);
1492 }
1493
1494 /**
1495  * g_file_info_set_is_hidden:
1496  * @info: a #GFileInfo.
1497  * @is_hidden: a #gboolean.
1498  * 
1499  * Sets the "is_hidden" attribute in a #GFileInfo according to @is_symlink.
1500  * See %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
1501  **/
1502 void
1503 g_file_info_set_is_hidden (GFileInfo *info,
1504                            gboolean   is_hidden)
1505 {
1506   static guint32 attr = 0;
1507   GFileAttributeValue *value;
1508   
1509   g_return_if_fail (G_IS_FILE_INFO (info));
1510   
1511   if (attr == 0)
1512     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
1513   
1514   value = g_file_info_create_value (info, attr);
1515   if (value)
1516     _g_file_attribute_value_set_boolean (value, is_hidden);
1517 }
1518
1519 /**
1520  * g_file_info_set_is_symlink:
1521  * @info: a #GFileInfo.
1522  * @is_symlink: a #gboolean.
1523  * 
1524  * Sets the "is_symlink" attribute in a #GFileInfo according to @is_symlink.
1525  * See %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
1526  **/
1527 void
1528 g_file_info_set_is_symlink (GFileInfo *info,
1529                             gboolean   is_symlink)
1530 {
1531   static guint32 attr = 0;
1532   GFileAttributeValue *value;
1533   
1534   g_return_if_fail (G_IS_FILE_INFO (info));
1535   
1536   if (attr == 0)
1537     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
1538   
1539   value = g_file_info_create_value (info, attr);
1540   if (value)
1541     _g_file_attribute_value_set_boolean (value, is_symlink);
1542 }
1543
1544 /**
1545  * g_file_info_set_name:
1546  * @info: a #GFileInfo.
1547  * @name: a string containing a name.
1548  * 
1549  * Sets the name attribute for the current #GFileInfo. 
1550  * See %G_FILE_ATTRIBUTE_STANDARD_NAME.
1551  **/
1552 void
1553 g_file_info_set_name (GFileInfo  *info,
1554                       const char *name)
1555 {
1556   static guint32 attr = 0;
1557   GFileAttributeValue *value;
1558   
1559   g_return_if_fail (G_IS_FILE_INFO (info));
1560   g_return_if_fail (name != NULL);
1561   
1562   if (attr == 0)
1563     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
1564   
1565   value = g_file_info_create_value (info, attr);
1566   if (value)
1567     _g_file_attribute_value_set_byte_string (value, name);
1568 }
1569
1570 /**
1571  * g_file_info_set_display_name:
1572  * @info: a #GFileInfo.
1573  * @display_name: a string containing a display name.
1574  * 
1575  * Sets the display name for the current #GFileInfo.
1576  * See %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
1577  **/
1578 void
1579 g_file_info_set_display_name (GFileInfo  *info,
1580                               const char *display_name)
1581 {
1582   static guint32 attr = 0;
1583   GFileAttributeValue *value;
1584   
1585   g_return_if_fail (G_IS_FILE_INFO (info));
1586   g_return_if_fail (display_name != NULL);
1587   
1588   if (attr == 0)
1589     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
1590   
1591   value = g_file_info_create_value (info, attr);
1592   if (value)
1593     _g_file_attribute_value_set_string (value, display_name);
1594 }
1595
1596 /**
1597  * g_file_info_set_edit_name:
1598  * @info: a #GFileInfo.
1599  * @edit_name: a string containing an edit name.
1600  * 
1601  * Sets the edit name for the current file.
1602  * See %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
1603  **/
1604 void
1605 g_file_info_set_edit_name (GFileInfo  *info,
1606                            const char *edit_name)
1607 {
1608   static guint32 attr = 0;
1609   GFileAttributeValue *value;
1610   
1611   g_return_if_fail (G_IS_FILE_INFO (info));
1612   g_return_if_fail (edit_name != NULL);
1613   
1614   if (attr == 0)
1615     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
1616   
1617   value = g_file_info_create_value (info, attr);
1618   if (value)
1619     _g_file_attribute_value_set_string (value, edit_name);
1620 }
1621
1622 /**
1623  * g_file_info_set_icon:
1624  * @info: a #GFileInfo.
1625  * @icon: a #GIcon.
1626  * 
1627  * Sets the icon for a given #GFileInfo. 
1628  * See %G_FILE_ATTRIBUTE_STANDARD_ICON.
1629  **/
1630 void
1631 g_file_info_set_icon (GFileInfo *info,
1632                       GIcon     *icon)
1633 {
1634   static guint32 attr = 0;
1635   GFileAttributeValue *value;
1636   
1637   g_return_if_fail (G_IS_FILE_INFO (info));
1638   g_return_if_fail (G_IS_ICON (icon));
1639   
1640   if (attr == 0)
1641     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
1642   
1643   value = g_file_info_create_value (info, attr);
1644   if (value)
1645     _g_file_attribute_value_set_object (value, G_OBJECT (icon));
1646 }
1647
1648 /**
1649  * g_file_info_set_content_type:
1650  * @info: a #GFileInfo.
1651  * @content_type: a content type. See #GContentType.
1652  * 
1653  * Sets the content type attribute for a given #GFileInfo.
1654  * See %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
1655  **/
1656 void
1657 g_file_info_set_content_type (GFileInfo  *info,
1658                               const char *content_type)
1659 {
1660   static guint32 attr = 0;
1661   GFileAttributeValue *value;
1662   
1663   g_return_if_fail (G_IS_FILE_INFO (info));
1664   g_return_if_fail (content_type != NULL);
1665   
1666   if (attr == 0)
1667     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1668   
1669   value = g_file_info_create_value (info, attr);
1670   if (value)
1671     _g_file_attribute_value_set_string (value, content_type);
1672 }
1673
1674 /**
1675  * g_file_info_set_size:
1676  * @info: a #GFileInfo.
1677  * @size: a #goffset containing the file's size.
1678  * 
1679  * Sets the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in the file info 
1680  * to the given size.
1681  **/
1682 void
1683 g_file_info_set_size (GFileInfo *info,
1684                       goffset    size)
1685 {
1686   static guint32 attr = 0;
1687   GFileAttributeValue *value;
1688   
1689   g_return_if_fail (G_IS_FILE_INFO (info));
1690   
1691   if (attr == 0)
1692     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
1693   
1694   value = g_file_info_create_value (info, attr);
1695   if (value)
1696     _g_file_attribute_value_set_uint64 (value, size);
1697 }
1698
1699 /**
1700  * g_file_info_set_modification_time
1701  * @info: a #GFileInfo.
1702  * @mtime: a #GTimeVal.
1703  * 
1704  * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED attribute in the file
1705  * info to the given time value.
1706  **/
1707 void
1708 g_file_info_set_modification_time (GFileInfo *info,
1709                                    GTimeVal  *mtime)
1710 {
1711   static guint32 attr_mtime = 0, attr_mtime_usec;
1712   GFileAttributeValue *value;
1713   
1714   g_return_if_fail (G_IS_FILE_INFO (info));
1715   g_return_if_fail (mtime != NULL);
1716   
1717   if (attr_mtime == 0)
1718     {
1719       attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1720       attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1721     }
1722   
1723   value = g_file_info_create_value (info, attr_mtime);
1724   if (value)
1725     _g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
1726   value = g_file_info_create_value (info, attr_mtime_usec);
1727   if (value)
1728     _g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
1729 }
1730
1731 /**
1732  * g_file_info_set_symlink_target:
1733  * @info: a #GFileInfo.
1734  * @symlink_target: a static string containing a path to a symlink target.
1735  * 
1736  * Sets the %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET attribute in the file info 
1737  * to the given symlink target.
1738  **/
1739 void
1740 g_file_info_set_symlink_target (GFileInfo  *info,
1741                                 const char *symlink_target)
1742 {
1743   static guint32 attr = 0;
1744   GFileAttributeValue *value;
1745   
1746   g_return_if_fail (G_IS_FILE_INFO (info));
1747   g_return_if_fail (symlink_target != NULL);
1748   
1749   if (attr == 0)
1750     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
1751   
1752   value = g_file_info_create_value (info, attr);
1753   if (value)
1754     _g_file_attribute_value_set_byte_string (value, symlink_target);
1755 }
1756
1757 /**
1758  * g_file_info_set_sort_order:
1759  * @info: a #GFileInfo.
1760  * @sort_order: a sort order integer.
1761  * 
1762  * Sets the sort order attribute in the file info structure. See 
1763  * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
1764  **/
1765 void
1766 g_file_info_set_sort_order (GFileInfo *info,
1767                             gint32     sort_order)
1768 {
1769   static guint32 attr = 0;
1770   GFileAttributeValue *value;
1771   
1772   g_return_if_fail (G_IS_FILE_INFO (info));
1773   
1774   if (attr == 0)
1775     attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
1776   
1777   value = g_file_info_create_value (info, attr);
1778   if (value)
1779     _g_file_attribute_value_set_int32 (value, sort_order);
1780 }
1781
1782
1783 #define ON_STACK_MATCHERS 5
1784
1785 typedef struct {
1786   guint32 id;
1787   guint32 mask;
1788 } SubMatcher;
1789
1790 struct _GFileAttributeMatcher {
1791   gboolean all;
1792   SubMatcher sub_matchers[ON_STACK_MATCHERS];
1793   GArray *more_sub_matchers;
1794
1795   /* Interator */
1796   guint32 iterator_ns;
1797   int iterator_pos;
1798   int ref;
1799 };
1800
1801 static void
1802 matcher_add (GFileAttributeMatcher *matcher,
1803              guint                  id,
1804              guint                  mask)
1805 {
1806   SubMatcher *sub_matchers;
1807   int i;
1808   SubMatcher s;
1809
1810   for (i = 0; i < ON_STACK_MATCHERS; i++)
1811     {
1812       /* First empty spot, not found, use this */
1813       if (matcher->sub_matchers[i].id == 0)
1814         {
1815           matcher->sub_matchers[i].id = id;
1816           matcher->sub_matchers[i].mask = mask;
1817           return;
1818         }
1819       
1820       /* Already added */
1821       if (matcher->sub_matchers[i].id == id &&
1822           matcher->sub_matchers[i].mask == mask)
1823         return;
1824     }
1825
1826   if (matcher->more_sub_matchers == NULL)
1827     matcher->more_sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
1828       
1829   sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
1830   for (i = 0; i < matcher->more_sub_matchers->len; i++)
1831     {
1832       /* Already added */
1833       if (sub_matchers[i].id == id &&
1834           sub_matchers[i].mask == mask)
1835         return;
1836     }
1837
1838   s.id = id;
1839   s.mask = mask;
1840   
1841   g_array_append_val (matcher->more_sub_matchers, s);
1842 }
1843
1844 /**
1845  * g_file_attribute_matcher_new:
1846  * @attributes: an attribute string to match.
1847  * 
1848  * Creates a new file attribute matcher, which matches attributes 
1849  * against a given string. #GFileAttributeMatcher<!-- -->s are reference 
1850  * counted structures, and are created with a reference count of 1. If 
1851  * the number of references falls to 0, the #GFileAttributeMatcher is 
1852  * automatically destroyed.
1853  * 
1854  * The @attribute string should be formatted with specific keys separated
1855  * from namespaces with a double colon. Several "namespace::key" strings may be 
1856  * concatenated with a single comma (e.g. "standard::type,standard::is-hidden"). 
1857  * The wildcard "*" may be used to match all keys and namespaces, or 
1858  * "namespace::*" will match all keys in a given namespace. 
1859  * 
1860  * Examples of strings to use:
1861  * <table>
1862  * <title>File Attribute Matcher strings and results</title>
1863  * <tgroup cols='2' align='left'><thead>
1864  * <row><entry> Matcher String </entry><entry> Matches </entry></row></thead>
1865  * <tbody>
1866  * <row><entry>"*"</entry><entry>matches all attributes.</entry></row>
1867  * <row><entry>"standard::is-hidden"</entry><entry>matches only the key is-hidden in the standard namespace.</entry></row>
1868  * <row><entry>"standard::type,unix::*"</entry><entry>matches the type key in the standard namespace and
1869  * all keys in the unix namespace.</entry></row>
1870  * </tbody></tgroup>
1871  * </table>
1872  * 
1873  * Returns: a #GFileAttributeMatcher.
1874  **/
1875 GFileAttributeMatcher *
1876 g_file_attribute_matcher_new (const char *attributes)
1877 {
1878   char **split;
1879   char *colon;
1880   int i;
1881   GFileAttributeMatcher *matcher;
1882
1883   if (attributes == NULL || *attributes == '\0')
1884     return NULL;
1885
1886   matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
1887   matcher->ref = 1;
1888
1889   split = g_strsplit (attributes, ",", -1);
1890
1891   for (i = 0; split[i] != NULL; i++)
1892     {
1893       if (strcmp (split[i], "*") == 0)
1894         matcher->all = TRUE;
1895       else
1896         {
1897           guint32 id, mask;
1898   
1899           colon = strstr (split[i], "::");
1900           if (colon != NULL &&
1901               !(colon[2] == 0 ||
1902                 (colon[2] == '*' &&
1903                  colon[3] == 0)))
1904             {
1905               id = lookup_attribute (split[i]);
1906               mask = 0xffffffff;
1907             }
1908           else
1909             {
1910               if (colon)
1911                 *colon = 0;
1912
1913               id = lookup_namespace (split[i]) << NS_POS;
1914               mask = NS_MASK << NS_POS;
1915             }
1916           
1917           matcher_add (matcher, id, mask);
1918         }
1919     }
1920
1921   g_strfreev (split);
1922
1923   return matcher;
1924 }
1925
1926 /**
1927  * g_file_attribute_matcher_ref:
1928  * @matcher: a #GFileAttributeMatcher.
1929  * 
1930  * References a file attribute matcher.
1931  * 
1932  * Returns: a #GFileAttributeMatcher.
1933  **/
1934 GFileAttributeMatcher *
1935 g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
1936 {
1937   if (matcher)
1938     {
1939       g_return_val_if_fail (matcher->ref > 0, NULL);
1940       g_atomic_int_inc (&matcher->ref);
1941     }
1942   return matcher;
1943 }
1944
1945 /**
1946  * g_file_attribute_matcher_unref:
1947  * @matcher: a #GFileAttributeMatcher.
1948  * 
1949  * Unreferences @matcher. If the reference count falls below 1, 
1950  * the @matcher is automatically freed.
1951  * 
1952  **/
1953 void
1954 g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
1955 {
1956   if (matcher)
1957     {
1958       g_return_if_fail (matcher->ref > 0);
1959       
1960       if (g_atomic_int_dec_and_test (&matcher->ref))
1961         {
1962           if (matcher->more_sub_matchers)
1963             g_array_free (matcher->more_sub_matchers, TRUE);
1964           
1965           g_free (matcher);
1966         }
1967     }
1968 }
1969
1970 /**
1971  * g_file_attribute_matcher_matches_only:
1972  * @matcher: a #GFileAttributeMatcher.
1973  * @attribute: a file attribute key.
1974  * 
1975  * Checks if a attribute matcher only matches a given attribute. Always
1976  * returns %FALSE if "*" was used when creating the matcher.
1977  * 
1978  * Returns: %TRUE if the matcher only matches @attribute. %FALSE otherwise.
1979  **/
1980 gboolean
1981 g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
1982                                        const char            *attribute)
1983 {
1984   guint32 id;
1985
1986   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
1987
1988   if (matcher == NULL ||
1989       matcher->all)
1990     return FALSE;
1991   
1992   id = lookup_attribute (attribute);
1993
1994   if (matcher->sub_matchers[0].id != 0 &&
1995       matcher->sub_matchers[1].id == 0 &&
1996       matcher->sub_matchers[0].mask == 0xffffffff &&
1997       matcher->sub_matchers[0].id == id)
1998     return TRUE;
1999   
2000   return FALSE;
2001 }
2002
2003 static gboolean
2004 matcher_matches_id (GFileAttributeMatcher *matcher,
2005                     guint32                id)
2006 {
2007   SubMatcher *sub_matchers;
2008   int i;
2009   
2010   for (i = 0; i < ON_STACK_MATCHERS; i++)
2011     {
2012       if (matcher->sub_matchers[i].id == 0)
2013         return FALSE;
2014       
2015       if (matcher->sub_matchers[i].id == (id & matcher->sub_matchers[i].mask))
2016         return TRUE;
2017     }
2018
2019   if (matcher->more_sub_matchers)
2020     {
2021       sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
2022       for (i = 0; i < matcher->more_sub_matchers->len; i++)
2023         {
2024           if (sub_matchers[i].id == (id & sub_matchers[i].mask))
2025             return TRUE;
2026         }
2027     }
2028   
2029   return FALSE;
2030 }
2031
2032 static gboolean
2033 g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
2034                                      guint32                id)
2035 {
2036   /* We return a NULL matcher for an empty match string, so handle this */
2037   if (matcher == NULL)
2038     return FALSE;
2039   
2040   if (matcher->all)
2041     return TRUE;
2042   
2043   return matcher_matches_id (matcher, id);
2044 }
2045
2046 /**
2047  * g_file_attribute_matcher_matches:
2048  * @matcher: a #GFileAttributeMatcher.
2049  * @attribute: a file attribute key.
2050  *
2051  * Checks if an attribute will be matched by an attribute matcher. If 
2052  * the matcher was created with the "*" matching string, this function
2053  * will always return %TRUE.
2054  * 
2055  * Returns: %TRUE if @attribute matches @matcher. %FALSE otherwise.
2056  **/
2057 gboolean
2058 g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
2059                                   const char            *attribute)
2060 {
2061   g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2062
2063   /* We return a NULL matcher for an empty match string, so handle this */
2064   if (matcher == NULL)
2065     return FALSE;
2066   
2067   if (matcher->all)
2068     return TRUE;
2069   
2070   return matcher_matches_id (matcher, lookup_attribute (attribute));
2071 }
2072
2073 /* return TRUE -> all */
2074 /**
2075  * g_file_attribute_matcher_enumerate_namespace:
2076  * @matcher: a #GFileAttributeMatcher.
2077  * @ns: a string containing a file attribute namespace.
2078  * 
2079  * Checks if the matcher will match all of the keys in a given namespace.
2080  * This will always return %TRUE if a wildcard character is in use (e.g. if 
2081  * matcher was created with "standard::*" and @ns is "standard", or if matcher was created
2082  * using "*" and namespace is anything.) 
2083  * 
2084  * TODO: this is awkwardly worded.
2085  * 
2086  * Returns: %TRUE if the matcher matches all of the entries
2087  * in the given @ns, %FALSE otherwise.
2088  **/
2089 gboolean
2090 g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
2091                                               const char            *ns)
2092 {
2093   SubMatcher *sub_matchers;
2094   int ns_id;
2095   int i;
2096   
2097   g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
2098
2099   /* We return a NULL matcher for an empty match string, so handle this */
2100   if (matcher == NULL)
2101     return FALSE;
2102   
2103   if (matcher->all)
2104     return TRUE;
2105
2106   ns_id = lookup_namespace (ns) << NS_POS;
2107
2108   for (i = 0; i < ON_STACK_MATCHERS; i++)
2109     {
2110       if (matcher->sub_matchers[i].id == ns_id)
2111         return TRUE;
2112     }
2113
2114   if (matcher->more_sub_matchers)
2115     {
2116       sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data;
2117       for (i = 0; i < matcher->more_sub_matchers->len; i++)
2118         {
2119           if (sub_matchers[i].id == ns_id)
2120             return TRUE;
2121         }
2122     }
2123
2124   matcher->iterator_ns = ns_id;
2125   matcher->iterator_pos = 0;
2126   
2127   return FALSE;
2128 }
2129
2130 /**
2131  * g_file_attribute_matcher_enumerate_next:
2132  * @matcher: a #GFileAttributeMatcher.
2133  * 
2134  * Gets the next matched attribute from a #GFileAttributeMatcher.
2135  * 
2136  * Returns: a string containing the next attribute or %NULL if 
2137  * no more attribute exist.
2138  **/
2139 const char *
2140 g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
2141 {
2142   int i;
2143   SubMatcher *sub_matcher;
2144
2145   /* We return a NULL matcher for an empty match string, so handle this */
2146   if (matcher == NULL)
2147     return NULL;
2148
2149   while (1)
2150     {
2151       i = matcher->iterator_pos++;
2152
2153       if (i < ON_STACK_MATCHERS)
2154         {
2155           if (matcher->sub_matchers[i].id == 0)
2156             return NULL;
2157
2158           sub_matcher = &matcher->sub_matchers[i];
2159         }
2160       else
2161         {
2162           if (matcher->more_sub_matchers == NULL)
2163             return NULL;
2164       
2165           i -= ON_STACK_MATCHERS;
2166           if (i < matcher->more_sub_matchers->len)
2167             sub_matcher = &g_array_index (matcher->more_sub_matchers, SubMatcher, i);
2168           else
2169             return NULL;
2170         }
2171
2172       if (sub_matcher->mask == 0xffffffff &&
2173           (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
2174         return get_attribute_for_id (sub_matcher->id);
2175     }
2176 }
2177
2178 #define __G_FILE_INFO_C__
2179 #include "gioaliasdef.c"