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