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