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