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