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