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