Fixes unknown meaning in GAppLaunchContext docs. Clarify asynchronous ops.
[platform/upstream/glib.git] / gio / gfileattribute.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 #include <config.h>
24
25 #include <string.h>
26
27 #include "gfileattribute.h"
28 #include <glib-object.h>
29 #include "glibintl.h"
30
31 #include "gioalias.h"
32
33 /**
34  * SECTION:gfileattribute
35  * @short_description: Key-Value Paired File Attributes
36  * @see_also: #GFile, #GFileInfo
37  * 
38  * File attributes in GIO consist of a list of key-value pairs. 
39  * 
40  * Keys are strings that contain a key namespace and a key name, separated
41  * by a colon, e.g. "namespace:keyname". Namespaces are included to sort
42  * key-value pairs by namespaces for relevance. Keys can be searched 
43  * for using wildcards, e.g. "std:*" will return all of the keys in the 
44  * "std" namespace.
45  * 
46  * Values are stored within the list in #GFileAttributeValue structures.
47  * Values can store different types, listed in the enum #GFileAttributeType.
48  * Upon creation of a #GFileAttributeValue, the type will be set to 
49  * %G_FILE_ATTRIBUTE_TYPE_INVALID. 
50  * 
51  * The Key-value list is stored within the #GFile structure as a 
52  * #GFileAttributeInfoList. This list is queryable by key names 
53  * as indicated earlier.
54  * 
55  * Classes that implement #GFileIface will create a #GFileAttributeInfoList and 
56  * install default keys and values for their given file system, architecture, 
57  * and other possible implementation details (e.g., on a UNIX system, a file 
58  * attribute key will be registered for the user id for a given file). Other 
59  * attributes can be appended to a #GFileAttributeList later by 
60  * g_file_attribute_info_list_add(). 
61  * 
62  * <para>
63  * <table>
64  * <title>GFileAttributes Namespaces</title>
65  * <tgroup cols='2' align='left'><thead>
66  * <row><entry>Namspace</entry><entry>Description</entry></row>
67  * </thead>
68  * <tbody>
69  * <row><entry>"std"</entry><entry>The "Standard" namespace. General file
70  * information that any application may need should be put in this namespace. Examples
71  * include the file's name, type, and size.</entry></row> 
72  * <row><entry>"etag"</entry><entry>The "Entity Tag" namespace. 
73  * GIO use "entity tags" to quickly determine if a file has been modified
74  * from the version on the file system. Entity tags are globally unique identifiers, 
75  * and should always be sent with the current revision of a file. 
76  * An example of a key in this namespace is "value", which contains the value of the 
77  * current entity tag.</entry></row>
78  * <row><entry>"id"</entry><entry>The "Identification" namespace. This 
79  * namespace is used by file managers and applications that list directories
80  * to check for loops and to uniquely identify files.</entry></row>
81  * <row><entry>"access"</entry><entry>The "Access" namespace. Used to check
82  * if a user has the proper privilidges to access files and perform
83  * file operations. Keys in this namespace are made to be generic 
84  * and easily understood, e.g. the "can_read" key is %TRUE if 
85  * the current user has permission to read the file. UNIX permissions and
86  * NTFS ACLs in Windows should be mapped to these values.</entry></row>
87  * <row><entry>"mountable"</entry><entry>The "Mountable" namespace. Includes 
88  * simple boolean keys for checking if a file or path supports mount operations, e.g.
89  * mount, unmount, eject.</entry></row>
90  * <row><entry>"time"</entry><entry>The "Time" namespace. Includes file 
91  * access, changed, created times. </entry></row>
92  * <row><entry>"unix"</entry><entry>The "Unix" namespace. Includes UNIX-specific
93  * information and may not be available for all files. Examples include 
94  * the UNIX "UID", "GID", etc.</entry></row>
95  * <row><entry>"dos"</entry><entry>The "DOS" namespace. Includes DOS-specific 
96  * information and may not be available for all files. Examples include
97  * "is_system" for checking if a file is marked as a system file, and "is_archive"
98  * for checking if a file is marked as an archive file.</entry></row>
99  * <row><entry>"owner"</entry><entry>The "Owner" namespace. Includes information
100  * about who owns a file. May not be available for all file systems. Examples include
101  * "user" for getting the user name of the file owner.</entry></row>
102  * <row><entry>"thumbnail"</entry><entry>The "Thumbnail" namespace. Includes 
103  * information about file thumbnails and their location within the file system. Exaples of 
104  * keys in this namespace include "path" to get the location of a thumbnail, and "failed"
105  * to check if thumbnailing failed.</entry></row>
106  * <row><entry>"fs"</entry><entry>The "Filesystem" namespace. Gets information
107  * about the file system where a file is located, such as its type, how much
108  * space is left available, and the overall size of the file system.</entry></row>
109  * <row><entry>"gvfs"</entry><entry>The "GVFS" namespace. Keys in this namespace
110  * contain information about the current GVFS backend in use. </entry></row>
111  * </tbody>
112  * </tgroup>
113  * </table>
114  * </para>
115  * 
116  * More namespaces can be added from GIO modules or by individual applications. 
117  * For more information about writing GIO modules, see #GIOModule.
118  * 
119  * <para><table>
120  * <title>GFileAttributes Built-in Keys and Value Types</title>
121  * <tgroup cols='3' align='left'><thead>
122  * <row><entry>Enum Value</entry><entry>Namespace:Key</entry><entry>Value Type</entry></row>
123  * </thead><tbody>
124  * <row><entry>%G_FILE_ATTRIBUTE_STD_TYPE</entry><entry>std:type</entry><entry>uint32 (#GFileType)</entry></row>
125  * <row><entry>%G_FILE_ATTRIBUTE_STD_IS_HIDDEN</entry><entry>std:is_hidden</entry><entry>boolean</entry></row>
126  * <row><entry>%G_FILE_ATTRIBUTE_STD_IS_BACKUP</entry><entry>std:is_backup</entry><entry>boolean</entry></row>
127  * <row><entry>%G_FILE_ATTRIBUTE_STD_IS_SYMLINK</entry><entry>std:is_symlink</entry><entry>boolean</entry></row>
128  * <row><entry>%G_FILE_ATTRIBUTE_STD_IS_VIRTUAL</entry><entry>std:is_virtual</entry><entry>boolean</entry></row>
129  * <row><entry>%G_FILE_ATTRIBUTE_STD_NAME</entry><entry>std:name</entry><entry>byte string</entry></row>
130  * <row><entry>%G_FILE_ATTRIBUTE_STD_DISPLAY_NAME</entry><entry>std:display_name</entry><entry>string</entry></row>
131  * <row><entry>%G_FILE_ATTRIBUTE_STD_EDIT_NAME</entry><entry>std:edit_name</entry><entry>string</entry></row>
132  * <row><entry>%G_FILE_ATTRIBUTE_STD_ICON</entry><entry>std:icon</entry><entry>object (#GIcon)</entry></row>
133  * <row><entry>%G_FILE_ATTRIBUTE_STD_CONTENT_TYPE</entry><entry>std:content_type</entry><entry>string</entry></row>
134  * <row><entry>%G_FILE_ATTRIBUTE_STD_FAST_CONTENT_TYPE</entry><entry>std:fast_content_type</entry><entry>string</entry></row>
135  * <row><entry>%G_FILE_ATTRIBUTE_STD_SIZE</entry><entry>std:size</entry><entry>uint64</entry></row>
136  * <row><entry>%G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET</entry><entry>std:symlink_target</entry><entry>byte string</entry></row>
137  * <row><entry>%G_FILE_ATTRIBUTE_STD_TARGET_URI</entry><entry>std:target_uri</entry><entry>string</entry></row>
138  * <row><entry>%G_FILE_ATTRIBUTE_STD_SORT_ORDER</entry><entry>std:sort_order</entry><entry>int32</entry></row>
139  * <row><entry>%G_FILE_ATTRIBUTE_ETAG_VALUE</entry><entry>etag:value</entry><entry>string</entry></row>
140  * <row><entry>%G_FILE_ATTRIBUTE_ID_FILE</entry><entry>id:file</entry><entry>string</entry></row>
141  * <row><entry>%G_FILE_ATTRIBUTE_ID_FS</entry><entry>id:fs</entry><entry>string</entry></row>
142  * <row><entry>%G_FILE_ATTRIBUTE_ACCESS_CAN_READ</entry><entry>access:can_read</entry><entry>boolean</entry></row>
143  * <row><entry>%G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE</entry><entry>access:can_write</entry><entry>boolean</entry></row>
144  * <row><entry>%G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE</entry><entry>access:can_execute</entry><entry>boolean</entry></row>
145  * <row><entry>%G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE</entry><entry>access:can_delete</entry><entry>boolean</entry></row>
146  * <row><entry>%G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH</entry><entry>access:can_trash</entry><entry>boolean</entry></row>
147  * <row><entry>%G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME</entry><entry>access:can_rename</entry><entry>boolean</entry></row>
148  * <row><entry>%G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT</entry><entry>mountable:can_mount</entry><entry>boolean</entry></row>
149  * <row><entry>%G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT</entry><entry>mountable:can_unmount</entry><entry>boolean</entry></row>
150  * <row><entry>%G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT</entry><entry>mountable:can_eject</entry><entry>boolean</entry></row>
151  * <row><entry>%G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE</entry><entry>mountable:unix_device</entry><entry>uint32</entry></row>
152  * <row><entry>%G_FILE_ATTRIBUTE_MOUNTABLE_HAL_UDI</entry><entry>mountable:hal_udi</entry><entry>string</entry></row>
153  * <row><entry>%G_FILE_ATTRIBUTE_TIME_MODIFIED</entry><entry>time:modified</entry><entry>uint64</entry></row>
154  * <row><entry>%G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC</entry><entry>time:modified_usec</entry><entry>uint32</entry></row>
155  * <row><entry>%G_FILE_ATTRIBUTE_TIME_ACCESS</entry><entry>time:access</entry><entry>uint64</entry></row>
156  * <row><entry>%G_FILE_ATTRIBUTE_TIME_ACCESS_USEC</entry><entry>time:access_usec</entry><entry>uint32</entry></row>
157  * <row><entry>%G_FILE_ATTRIBUTE_TIME_CHANGED</entry><entry>time:changed</entry><entry>uint64</entry></row>
158  * <row><entry>%G_FILE_ATTRIBUTE_TIME_CHANGED_USEC</entry><entry>time:changed_usec</entry><entry>uint32</entry></row>
159  * <row><entry>%G_FILE_ATTRIBUTE_TIME_CREATED</entry><entry>time:created</entry><entry>uint64</entry></row>
160  * <row><entry>%G_FILE_ATTRIBUTE_TIME_CREATED_USEC</entry><entry>time:created_usec</entry><entry>uint32</entry></row>
161  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_DEVICE</entry><entry>unix:device</entry><entry>uint32</entry></row>
162  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_INODE</entry><entry>unix:inode</entry><entry>uint64</entry></row>
163  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_MODE</entry><entry>unix:mode</entry><entry>uint32</entry></row>
164  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_NLINK</entry><entry>unix:nlink</entry><entry>uint32</entry></row>
165  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_UID</entry><entry>unix:uid</entry><entry>uint32</entry></row>
166  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_GID</entry><entry>unix:gid</entry><entry>uint32</entry></row>
167  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_RDEV</entry><entry>unix:rdev</entry><entry>uint32</entry></row>
168  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE</entry><entry>unix:block_size</entry><entry>uint32</entry></row>
169  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_BLOCKS</entry><entry>unix:blocks</entry><entry>uint64</entry></row>
170  * <row><entry>%G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT</entry><entry>unix:is_mountpoint</entry><entry>boolean</entry></row>
171  * <row><entry>%G_FILE_ATTRIBUTE_DOS_IS_ARCHIVE</entry><entry>dos:is_archive</entry><entry>boolean</entry></row>
172  * <row><entry>%G_FILE_ATTRIBUTE_DOS_IS_SYSTEM</entry><entry>dos:is_system</entry><entry>boolean</entry></row>
173  * <row><entry>%G_FILE_ATTRIBUTE_OWNER_USER</entry><entry>owner:user</entry><entry>string</entry></row>
174  * <row><entry>%G_FILE_ATTRIBUTE_OWNER_USER_REAL</entry><entry>owner:user_real</entry><entry>string</entry></row>
175  * <row><entry>%G_FILE_ATTRIBUTE_OWNER_GROUP</entry><entry>owner:group</entry><entry>string</entry></row>
176  * <row><entry>%G_FILE_ATTRIBUTE_THUMBNAIL_PATH</entry><entry>thumbnail:path</entry><entry>bytestring</entry></row>
177  * <row><entry>%G_FILE_ATTRIBUTE_THUMBNAILING_FAILED</entry><entry>thumbnail:failed</entry><entry>boolean</entry></row>
178  * <row><entry>%G_FILE_ATTRIBUTE_FS_SIZE</entry><entry>fs:size</entry><entry>uint64</entry></row>
179  * <row><entry>%G_FILE_ATTRIBUTE_FS_FREE</entry><entry>fs:free</entry><entry>uint64</entry></row>
180  * <row><entry>%G_FILE_ATTRIBUTE_FS_TYPE</entry><entry>fs:type</entry><entry>string</entry></row>
181  * <row><entry>%G_FILE_ATTRIBUTE_FS_READONLY</entry><entry>fs:readonly</entry><entry>boolean</entry></row>
182  * <row><entry>%G_FILE_ATTRIBUTE_GVFS_BACKEND</entry><entry>gvfs:backend</entry><entry>string</entry></row>
183  * </tbody></tgroup></table></para>
184  *  
185  **/ 
186
187 /**
188  * g_file_attribute_value_free:
189  * @attr: a #GFileAttributeValue. 
190  * 
191  * Frees the memory used by @attr.
192  *
193  **/
194 void
195 g_file_attribute_value_free (GFileAttributeValue *attr)
196 {
197   g_return_if_fail (attr != NULL);
198
199   g_file_attribute_value_clear (attr);
200   g_free (attr);
201 }
202
203 /**
204  * g_file_attribute_value_clear:
205  * @attr: a #GFileAttributeValue.
206  *
207  * Clears the value of @attr and sets its type to 
208  * %G_FILE_ATTRIBUTE_TYPE_INVALID.
209  * 
210  **/
211 void
212 g_file_attribute_value_clear (GFileAttributeValue *attr)
213 {
214   g_return_if_fail (attr != NULL);
215
216   if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
217       attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
218     g_free (attr->u.string);
219   
220   if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
221       attr->u.obj != NULL)
222     g_object_unref (attr->u.obj);
223   
224   attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
225 }
226
227 /**
228  * g_file_attribute_value_set:
229  * @attr: a #GFileAttributeValue to set the value in.
230  * @new_value: a #GFileAttributeValue to get the value from.
231  * 
232  * Sets an attribute's value from another attribute.
233  **/
234 void
235 g_file_attribute_value_set (GFileAttributeValue        *attr,
236                             const GFileAttributeValue *new_value)
237 {
238   g_return_if_fail (attr != NULL);
239   g_return_if_fail (new_value != NULL);
240
241   g_file_attribute_value_clear (attr);
242   *attr = *new_value;
243
244   if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
245       attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
246     attr->u.string = g_strdup (attr->u.string);
247   
248   if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
249       attr->u.obj != NULL)
250     g_object_ref (attr->u.obj);
251 }
252
253 /**
254  * g_file_attribute_value_new:
255  * 
256  * Creates a new file attribute.
257  * 
258  * Returns: a #GFileAttributeValue.
259  **/
260 GFileAttributeValue *
261 g_file_attribute_value_new (void)
262 {
263   GFileAttributeValue *attr;
264
265   attr = g_new (GFileAttributeValue, 1);
266   attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
267   return attr;
268 }
269
270
271 /**
272  * g_file_attribute_value_dup:
273  * @other: a #GFileAttributeValue to duplicate.
274  * 
275  * Duplicates a file attribute.
276  * 
277  * Returns: a duplicate of the @other.
278  **/
279 GFileAttributeValue *
280 g_file_attribute_value_dup (const GFileAttributeValue *other)
281 {
282   GFileAttributeValue *attr;
283
284   g_return_val_if_fail (other != NULL, NULL);
285
286   attr = g_new (GFileAttributeValue, 1);
287   attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
288   g_file_attribute_value_set (attr, other);
289   return attr;
290 }
291
292 static gboolean
293 valid_char (char c)
294 {
295   return c >= 32 && c <= 126 && c != '\\';
296 }
297
298 static char *
299 escape_byte_string (const char *str)
300 {
301   size_t len;
302   int num_invalid, i;
303   char *escaped_val, *p;
304   unsigned char c;
305   char *hex_digits = "0123456789abcdef";
306   
307   len = strlen (str);
308   
309   num_invalid = 0;
310   for (i = 0; i < len; i++)
311     {
312       if (!valid_char (str[i]))
313         num_invalid++;
314     }
315         
316   if (num_invalid == 0)
317     return g_strdup (str);
318   else
319     {
320       escaped_val = g_malloc (len + num_invalid*3 + 1);
321
322       p = escaped_val;
323       for (i = 0; i < len; i++)
324         {
325           c = str[i];
326           if (valid_char (c))
327             *p++ = c;
328           else
329             {
330               *p++ = '\\';
331               *p++ = 'x';
332               *p++ = hex_digits[(c >> 8) & 0xf];
333               *p++ = hex_digits[c & 0xf];
334             }
335         }
336       *p++ = 0;
337       return escaped_val;
338     }
339 }
340
341 /**
342  * g_file_attribute_value_as_string:
343  * @attr: a #GFileAttributeValue.
344  *
345  * Converts a #GFileAttributeValue to a string for display.
346  * The returned string should be freed when no longer needed.
347  * 
348  * Returns: a string from the @attr, %NULL on error, or "&lt;invalid&gt;" 
349  * if @attr is of type %G_FILE_ATTRIBUTE_TYPE_INVALID.
350  **/
351 char *
352 g_file_attribute_value_as_string (const GFileAttributeValue *attr)
353 {
354   char *str;
355
356   g_return_val_if_fail (attr != NULL, NULL);
357
358   switch (attr->type)
359     {
360     case G_FILE_ATTRIBUTE_TYPE_STRING:
361       str = g_strdup (attr->u.string);
362       break;
363     case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
364       str = escape_byte_string (attr->u.string);
365       break;
366     case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
367       str = g_strdup_printf ("%s", attr->u.boolean?"TRUE":"FALSE");
368       break;
369     case G_FILE_ATTRIBUTE_TYPE_UINT32:
370       str = g_strdup_printf ("%u", (unsigned int)attr->u.uint32);
371       break;
372     case G_FILE_ATTRIBUTE_TYPE_INT32:
373       str = g_strdup_printf ("%i", (int)attr->u.int32);
374       break;
375     case G_FILE_ATTRIBUTE_TYPE_UINT64:
376       str = g_strdup_printf ("%"G_GUINT64_FORMAT, attr->u.uint64);
377       break;
378     case G_FILE_ATTRIBUTE_TYPE_INT64:
379       str = g_strdup_printf ("%"G_GINT64_FORMAT, attr->u.int64);
380       break;
381     case G_FILE_ATTRIBUTE_TYPE_OBJECT:
382       str = g_strdup_printf ("%s:%p", g_type_name_from_instance
383                                           ((GTypeInstance *) attr->u.obj),
384                                       attr->u.obj);
385       break;
386     default:
387       g_warning ("Invalid type in GFileInfo attribute");
388       str = g_strdup ("<invalid>");
389       break;
390     }
391   
392   return str;
393 }
394
395 /**
396  * g_file_attribute_value_get_string:
397  * @attr: a #GFileAttributeValue.
398  * 
399  * Gets the string from a file attribute value. If the value is not the
400  * right type then %NULL will be returned.
401  * 
402  * Returns: the string value contained within the attribute, or %NULL.
403  **/
404 const char *
405 g_file_attribute_value_get_string (const GFileAttributeValue *attr)
406 {
407   if (attr == NULL)
408     return NULL;
409
410   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING, NULL);
411
412   return attr->u.string;
413 }
414
415 /**
416  * g_file_attribute_value_get_byte_string:
417  * @attr: a #GFileAttributeValue.
418  * 
419  * Gets the byte string from a file attribute value. If the value is not the
420  * right type then %NULL will be returned.
421  * 
422  * Returns: the byte string contained within the attribute or %NULL.
423  **/
424 const char *
425 g_file_attribute_value_get_byte_string (const GFileAttributeValue *attr)
426 {
427   if (attr == NULL)
428     return NULL;
429
430   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, NULL);
431
432   return attr->u.string;
433 }
434   
435 /**
436  * g_file_attribute_value_get_boolean:
437  * @attr: a #GFileAttributeValue.
438  * 
439  * Gets the boolean value from a file attribute value. If the value is not the
440  * right type then %FALSE will be returned.
441  * 
442  * Returns: the boolean value contained within the attribute, or %FALSE.
443  **/
444 gboolean
445 g_file_attribute_value_get_boolean (const GFileAttributeValue *attr)
446 {
447   if (attr == NULL)
448     return FALSE;
449
450   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BOOLEAN, FALSE);
451
452   return attr->u.boolean;
453 }
454   
455 /**
456  * g_file_attribute_value_get_uint32:
457  * @attr: a #GFileAttributeValue.
458  * 
459  * Gets the unsigned 32-bit integer from a file attribute value. If the value 
460  * is not the right type then %0 will be returned.
461  * 
462  * Returns: the unsigned 32-bit integer from the attribute, or %0.
463  **/
464 guint32
465 g_file_attribute_value_get_uint32 (const GFileAttributeValue *attr)
466 {
467   if (attr == NULL)
468     return 0;
469
470   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT32, 0);
471
472   return attr->u.uint32;
473 }
474
475 /**
476  * g_file_attribute_value_get_int32:
477  * @attr: a #GFileAttributeValue.
478  * 
479  * Gets the signed 32-bit integer from a file attribute value. If the value 
480  * is not the right type then %0 will be returned.
481  * 
482  * Returns: the signed 32-bit integer from the attribute, or %0.
483  **/
484 gint32
485 g_file_attribute_value_get_int32 (const GFileAttributeValue *attr)
486 {
487   if (attr == NULL)
488     return 0;
489
490   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT32, 0);
491
492   return attr->u.int32;
493 }
494
495 /**
496  * g_file_attribute_value_get_uint64:
497  * @attr: a #GFileAttributeValue.
498  * 
499  * Gets the unsigned 64-bit integer from a file attribute value. If the value 
500  * is not the right type then %0 will be returned.
501  * 
502  * Returns: the unsigned 64-bit integer from the attribute, or %0.
503  **/  
504 guint64
505 g_file_attribute_value_get_uint64 (const GFileAttributeValue *attr)
506 {
507   if (attr == NULL)
508     return 0;
509
510   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT64, 0);
511
512   return attr->u.uint64;
513 }
514
515 /**
516  * g_file_attribute_value_get_int64:
517  * @attr: a #GFileAttributeValue.
518  * 
519  * Gets the signed 64-bit integer from a file attribute value. If the value 
520  * is not the right type then %0 will be returned.
521  * 
522  * Returns: the signed 64-bit integer from the attribute, or %0. 
523  **/
524 gint64
525 g_file_attribute_value_get_int64 (const GFileAttributeValue *attr)
526 {
527   if (attr == NULL)
528     return 0;
529
530   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT64, 0);
531
532   return attr->u.int64;
533 }
534
535 /**
536  * g_file_attribute_value_get_object:
537  * @attr: a #GFileAttributeValue.
538  * 
539  * Gets the GObject from a file attribute value. If the value 
540  * is not the right type then %NULL will be returned.
541  * 
542  * Returns: the GObject from the attribute, or %0.
543  **/
544 GObject *
545 g_file_attribute_value_get_object (const GFileAttributeValue *attr)
546 {
547   if (attr == NULL)
548     return NULL;
549
550   g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT, NULL);
551
552   return attr->u.obj;
553 }
554   
555 /**
556  * g_file_attribute_value_set_string:
557  * @attr: a #GFileAttributeValue.
558  * @string: a string to set within the type.
559  * 
560  * Sets the attribute value to a given string.
561  * 
562  **/
563 void
564 g_file_attribute_value_set_string (GFileAttributeValue *attr,
565                                    const char          *string)
566 {
567   g_return_if_fail (attr != NULL);
568   g_return_if_fail (string != NULL);
569
570   g_file_attribute_value_clear (attr);
571   attr->type = G_FILE_ATTRIBUTE_TYPE_STRING;
572   attr->u.string = g_strdup (string);
573 }
574
575 /**
576  * g_file_attribute_value_set_byte_string:
577  * @attr: a #GFileAttributeValue.
578  * @string: a byte string to set within the type.
579  * 
580  * Sets the attribute value to a given byte string.
581  * 
582  **/
583 void
584 g_file_attribute_value_set_byte_string (GFileAttributeValue *attr,
585                                         const char          *string)
586 {
587   g_return_if_fail (attr != NULL);
588   g_return_if_fail (string != NULL);
589
590   g_file_attribute_value_clear (attr);
591   attr->type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
592   attr->u.string = g_strdup (string);
593 }
594
595 /**
596  * g_file_attribute_value_set_boolean:
597  * @attr: a #GFileAttributeValue.
598  * @value: a #gboolean to set within the type.
599  * 
600  * Sets the attribute value to the given boolean value. 
601  * 
602  **/
603 void
604 g_file_attribute_value_set_boolean (GFileAttributeValue *attr,
605                                     gboolean             value)
606 {
607   g_return_if_fail (attr != NULL);
608
609   g_file_attribute_value_clear (attr);
610   attr->type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
611   attr->u.boolean = !!value;
612 }
613
614 /**
615  * g_file_attribute_value_set_uint32:
616  * @attr: a #GFileAttributeValue.
617  * @value: a #guint32 to set within the type.
618  * 
619  * Sets the attribute value to the given unsigned 32-bit integer.
620  * 
621  **/ 
622 void
623 g_file_attribute_value_set_uint32 (GFileAttributeValue *attr,
624                                    guint32              value)
625 {
626   g_return_if_fail (attr != NULL);
627
628   g_file_attribute_value_clear (attr);
629   attr->type = G_FILE_ATTRIBUTE_TYPE_UINT32;
630   attr->u.uint32 = value;
631 }
632
633 /**
634  * g_file_attribute_value_set_int32:
635  * @attr: a #GFileAttributeValue.
636  * @value: a #gint32 to set within the type.
637  * 
638  * Sets the attribute value to the given signed 32-bit integer.
639  *  
640  **/
641 void
642 g_file_attribute_value_set_int32 (GFileAttributeValue *attr,
643                                   gint32               value)
644 {
645   g_return_if_fail (attr != NULL);
646
647   g_file_attribute_value_clear (attr);
648   attr->type = G_FILE_ATTRIBUTE_TYPE_INT32;
649   attr->u.int32 = value;
650 }
651
652 /**
653  * g_file_attribute_value_set_uint64:
654  * @attr: a #GFileAttributeValue.
655  * @value: a #guint64 to set within the type.
656  * 
657  * Sets the attribute value to a given unsigned 64-bit integer.
658  * 
659  **/
660 void
661 g_file_attribute_value_set_uint64 (GFileAttributeValue *attr,
662                                    guint64              value)
663 {
664   g_return_if_fail (attr != NULL);
665
666   g_file_attribute_value_clear (attr);
667   attr->type = G_FILE_ATTRIBUTE_TYPE_UINT64;
668   attr->u.uint64 = value;
669 }
670
671 /**
672  * g_file_attribute_value_set_int64:
673  * @attr: a #GFileAttributeValue.
674  * @value: a #gint64 to set within the type.
675  * 
676  * Sets the attribute value to a given signed 64-bit integer. 
677  * 
678  **/
679 void
680 g_file_attribute_value_set_int64 (GFileAttributeValue *attr,
681                                   gint64               value)
682 {
683   g_return_if_fail (attr != NULL);
684
685   g_file_attribute_value_clear (attr);
686   attr->type = G_FILE_ATTRIBUTE_TYPE_INT64;
687   attr->u.int64 = value;
688 }
689
690 /**
691  * g_file_attribute_value_set_object:
692  * @attr: a #GFileAttributeValue.
693  * @obj: a #GObject.
694  *
695  * Sets the attribute to contain the value @obj.
696  * The @attr references the GObject internally.
697  * 
698  **/
699 void
700 g_file_attribute_value_set_object (GFileAttributeValue *attr,
701                                    GObject             *obj)
702 {
703   g_return_if_fail (attr != NULL);
704   g_return_if_fail (obj != NULL);
705
706   g_file_attribute_value_clear (attr);
707   attr->type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
708   attr->u.obj = g_object_ref (obj);
709 }
710
711 typedef struct {
712   GFileAttributeInfoList public;
713   GArray *array;
714   int ref_count;
715 } GFileAttributeInfoListPriv;
716
717 static void
718 list_update_public (GFileAttributeInfoListPriv *priv)
719 {
720   priv->public.infos = (GFileAttributeInfo *)priv->array->data;
721   priv->public.n_infos = priv->array->len;
722 }
723
724 /**
725  * g_file_attribute_info_list_new:
726  * 
727  * Creates a new file attribute info list.
728  * 
729  * Returns: a #GFileAttributeInfoList.
730  **/
731 GFileAttributeInfoList *
732 g_file_attribute_info_list_new (void)
733 {
734   GFileAttributeInfoListPriv *priv;
735
736   priv = g_new0 (GFileAttributeInfoListPriv, 1);
737   
738   priv->ref_count = 1;
739   priv->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
740   
741   list_update_public (priv);
742   
743   return (GFileAttributeInfoList *)priv;
744 }
745
746 /**
747  * g_file_attribute_info_list_dup:
748  * @list: a #GFileAttributeInfoList to duplicate.
749  * 
750  * Makes a duplicate of a file attribute info list.
751  * 
752  * Returns: a copy of the given @list. 
753  **/
754 GFileAttributeInfoList *
755 g_file_attribute_info_list_dup (GFileAttributeInfoList *list)
756 {
757   GFileAttributeInfoListPriv *new;
758   int i;
759   
760   g_return_val_if_fail (list != NULL, NULL);
761
762   new = g_new0 (GFileAttributeInfoListPriv, 1);
763   new->ref_count = 1;
764   new->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
765
766   g_array_set_size (new->array, list->n_infos);
767   list_update_public (new);
768   for (i = 0; i < list->n_infos; i++)
769     {
770       new->public.infos[i].name = g_strdup (list->infos[i].name);
771       new->public.infos[i].type = list->infos[i].type;
772       new->public.infos[i].flags = list->infos[i].flags;
773     }
774   
775   return (GFileAttributeInfoList *)new;
776 }
777
778 /**
779  * g_file_attribute_info_list_ref:
780  * @list: a #GFileAttributeInfoList to reference.
781  * 
782  * References a file attribute info list.
783  * 
784  * Returns: #GFileAttributeInfoList or %NULL on error.
785  **/
786 GFileAttributeInfoList *
787 g_file_attribute_info_list_ref (GFileAttributeInfoList *list)
788 {
789   GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
790   
791   g_return_val_if_fail (list != NULL, NULL);
792   g_return_val_if_fail (priv->ref_count > 0, NULL);
793   
794   g_atomic_int_inc (&priv->ref_count);
795   
796   return list;
797 }
798
799 /**
800  * g_file_attribute_info_list_unref:
801  * @list: The #GFileAttributeInfoList to unreference.
802  * 
803  * Removes a reference from the given @list. If the reference count
804  * falls to zero, the @list is deleted.
805  **/
806 void
807 g_file_attribute_info_list_unref (GFileAttributeInfoList *list)
808 {
809   GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
810   int i;
811   
812   g_return_if_fail (list != NULL);
813   g_return_if_fail (priv->ref_count > 0);
814   
815   if (g_atomic_int_dec_and_test (&priv->ref_count))
816     {
817       for (i = 0; i < list->n_infos; i++)
818         g_free (list->infos[i].name);
819       g_array_free (priv->array, TRUE);
820     }
821 }
822
823 static int
824 g_file_attribute_info_list_bsearch (GFileAttributeInfoList *list,
825                                     const char             *name)
826 {
827   int start, end, mid;
828   
829   start = 0;
830   end = list->n_infos;
831
832   while (start != end)
833     {
834       mid = start + (end - start) / 2;
835
836       if (strcmp (name, list->infos[mid].name) < 0)
837         end = mid;
838       else if (strcmp (name, list->infos[mid].name) > 0)
839         start = mid + 1;
840       else
841         return mid;
842     }
843   return start;
844 }
845
846 /**
847  * g_file_attribute_info_list_lookup:
848  * @list: a #GFileAttributeInfoList.
849  * @name: the name of the attribute to lookup.
850  * 
851  * Gets the file attribute with the name @name from @list.
852  *
853  * Returns: a #GFileAttributeInfo for the @name, or %NULL if an 
854  * attribute isn't found.
855  **/
856 const GFileAttributeInfo *
857 g_file_attribute_info_list_lookup (GFileAttributeInfoList *list,
858                                    const char             *name)
859 {
860   int i;
861   
862   g_return_val_if_fail (list != NULL, NULL);
863   g_return_val_if_fail (name != NULL, NULL);
864   
865   i = g_file_attribute_info_list_bsearch (list, name);
866
867   if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
868     return &list->infos[i];
869   
870   return NULL;
871 }
872
873 /**
874  * g_file_attribute_info_list_add:
875  * @list: a #GFileAttributeInfoList.
876  * @name: the name of the attribute to add.
877  * @type: the #GFileAttributeType for the attribute.
878  * @flags: #GFileAttributeFlags for the attribute.
879  * 
880  * Adds a new attribute with @name to the @list, setting
881  * its @type and @flags. 
882  **/
883 void
884 g_file_attribute_info_list_add    (GFileAttributeInfoList *list,
885                                    const char             *name,
886                                    GFileAttributeType      type,
887                                    GFileAttributeFlags     flags)
888 {
889   GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
890   GFileAttributeInfo info;
891   int i;
892   
893   g_return_if_fail (list != NULL);
894   g_return_if_fail (name != NULL);
895
896   i = g_file_attribute_info_list_bsearch (list, name);
897
898   if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
899     {
900       list->infos[i].type = type;
901       return;
902     }
903
904   info.name = g_strdup (name);
905   info.type = type;
906   info.flags = flags;
907   g_array_insert_vals (priv->array, i, &info, 1);
908
909   list_update_public (priv);
910 }
911
912 #define __G_FILE_ATTRIBUTE_C__
913 #include "gioaliasdef.c"