1 /* 2 * QEMU Object Model 3 * 4 * Copyright IBM, Corp. 2011 5 * 6 * Authors: 7 * Anthony Liguori <aliguori@us.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qom/object.h" 14 #include "qom/object_interfaces.h" 15 #include "qemu-common.h" 16 #include "qapi/visitor.h" 17 #include "qapi-visit.h" 18 #include "qapi/string-input-visitor.h" 19 #include "qapi/string-output-visitor.h" 20 #include "qapi/qmp/qerror.h" 21 #include "trace.h" 22 23 /* TODO: replace QObject with a simpler visitor to avoid a dependency 24 * of the QOM core on QObject? */ 25 #include "qom/qom-qobject.h" 26 #include "qapi/qmp/qobject.h" 27 #include "qapi/qmp/qbool.h" 28 #include "qapi/qmp/qint.h" 29 #include "qapi/qmp/qstring.h" 30 31 #define MAX_INTERFACES 32 32 33 typedef struct InterfaceImpl InterfaceImpl; 34 typedef struct TypeImpl TypeImpl; 35 36 struct InterfaceImpl 37 { 38 const char *typename; 39 }; 40 41 struct TypeImpl 42 { 43 const char *name; 44 45 size_t class_size; 46 47 size_t instance_size; 48 49 void (*class_init)(ObjectClass *klass, void *data); 50 void (*class_base_init)(ObjectClass *klass, void *data); 51 void (*class_finalize)(ObjectClass *klass, void *data); 52 53 void *class_data; 54 55 void (*instance_init)(Object *obj); 56 void (*instance_post_init)(Object *obj); 57 void (*instance_finalize)(Object *obj); 58 59 bool abstract; 60 61 const char *parent; 62 TypeImpl *parent_type; 63 64 ObjectClass *class; 65 66 int num_interfaces; 67 InterfaceImpl interfaces[MAX_INTERFACES]; 68 }; 69 70 struct ObjectPropertyIterator { 71 GHashTableIter iter; 72 }; 73 74 static Type type_interface; 75 76 static GHashTable *type_table_get(void) 77 { 78 static GHashTable *type_table; 79 80 if (type_table == NULL) { 81 type_table = g_hash_table_new(g_str_hash, g_str_equal); 82 } 83 84 return type_table; 85 } 86 87 static bool enumerating_types; 88 89 static void type_table_add(TypeImpl *ti) 90 { 91 assert(!enumerating_types); 92 g_hash_table_insert(type_table_get(), (void *)ti->name, ti); 93 } 94 95 static TypeImpl *type_table_lookup(const char *name) 96 { 97 return g_hash_table_lookup(type_table_get(), name); 98 } 99 100 static TypeImpl *type_new(const TypeInfo *info) 101 { 102 TypeImpl *ti = g_malloc0(sizeof(*ti)); 103 int i; 104 105 g_assert(info->name != NULL); 106 107 if (type_table_lookup(info->name) != NULL) { 108 fprintf(stderr, "Registering `%s' which already exists\n", info->name); 109 abort(); 110 } 111 112 ti->name = g_strdup(info->name); 113 ti->parent = g_strdup(info->parent); 114 115 ti->class_size = info->class_size; 116 ti->instance_size = info->instance_size; 117 118 ti->class_init = info->class_init; 119 ti->class_base_init = info->class_base_init; 120 ti->class_finalize = info->class_finalize; 121 ti->class_data = info->class_data; 122 123 ti->instance_init = info->instance_init; 124 ti->instance_post_init = info->instance_post_init; 125 ti->instance_finalize = info->instance_finalize; 126 127 ti->abstract = info->abstract; 128 129 for (i = 0; info->interfaces && info->interfaces[i].type; i++) { 130 ti->interfaces[i].typename = g_strdup(info->interfaces[i].type); 131 } 132 ti->num_interfaces = i; 133 134 return ti; 135 } 136 137 static TypeImpl *type_register_internal(const TypeInfo *info) 138 { 139 TypeImpl *ti; 140 ti = type_new(info); 141 142 type_table_add(ti); 143 return ti; 144 } 145 146 TypeImpl *type_register(const TypeInfo *info) 147 { 148 assert(info->parent); 149 return type_register_internal(info); 150 } 151 152 TypeImpl *type_register_static(const TypeInfo *info) 153 { 154 return type_register(info); 155 } 156 157 static TypeImpl *type_get_by_name(const char *name) 158 { 159 if (name == NULL) { 160 return NULL; 161 } 162 163 return type_table_lookup(name); 164 } 165 166 static TypeImpl *type_get_parent(TypeImpl *type) 167 { 168 if (!type->parent_type && type->parent) { 169 type->parent_type = type_get_by_name(type->parent); 170 g_assert(type->parent_type != NULL); 171 } 172 173 return type->parent_type; 174 } 175 176 static bool type_has_parent(TypeImpl *type) 177 { 178 return (type->parent != NULL); 179 } 180 181 static size_t type_class_get_size(TypeImpl *ti) 182 { 183 if (ti->class_size) { 184 return ti->class_size; 185 } 186 187 if (type_has_parent(ti)) { 188 return type_class_get_size(type_get_parent(ti)); 189 } 190 191 return sizeof(ObjectClass); 192 } 193 194 static size_t type_object_get_size(TypeImpl *ti) 195 { 196 if (ti->instance_size) { 197 return ti->instance_size; 198 } 199 200 if (type_has_parent(ti)) { 201 return type_object_get_size(type_get_parent(ti)); 202 } 203 204 return 0; 205 } 206 207 static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) 208 { 209 assert(target_type); 210 211 /* Check if target_type is a direct ancestor of type */ 212 while (type) { 213 if (type == target_type) { 214 return true; 215 } 216 217 type = type_get_parent(type); 218 } 219 220 return false; 221 } 222 223 static void type_initialize(TypeImpl *ti); 224 225 static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, 226 TypeImpl *parent_type) 227 { 228 InterfaceClass *new_iface; 229 TypeInfo info = { }; 230 TypeImpl *iface_impl; 231 232 info.parent = parent_type->name; 233 info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name); 234 info.abstract = true; 235 236 iface_impl = type_new(&info); 237 iface_impl->parent_type = parent_type; 238 type_initialize(iface_impl); 239 g_free((char *)info.name); 240 241 new_iface = (InterfaceClass *)iface_impl->class; 242 new_iface->concrete_class = ti->class; 243 new_iface->interface_type = interface_type; 244 245 ti->class->interfaces = g_slist_append(ti->class->interfaces, 246 iface_impl->class); 247 } 248 249 static void type_initialize(TypeImpl *ti) 250 { 251 TypeImpl *parent; 252 253 if (ti->class) { 254 return; 255 } 256 257 ti->class_size = type_class_get_size(ti); 258 ti->instance_size = type_object_get_size(ti); 259 260 ti->class = g_malloc0(ti->class_size); 261 262 parent = type_get_parent(ti); 263 if (parent) { 264 type_initialize(parent); 265 GSList *e; 266 int i; 267 268 g_assert_cmpint(parent->class_size, <=, ti->class_size); 269 memcpy(ti->class, parent->class, parent->class_size); 270 ti->class->interfaces = NULL; 271 272 for (e = parent->class->interfaces; e; e = e->next) { 273 InterfaceClass *iface = e->data; 274 ObjectClass *klass = OBJECT_CLASS(iface); 275 276 type_initialize_interface(ti, iface->interface_type, klass->type); 277 } 278 279 for (i = 0; i < ti->num_interfaces; i++) { 280 TypeImpl *t = type_get_by_name(ti->interfaces[i].typename); 281 for (e = ti->class->interfaces; e; e = e->next) { 282 TypeImpl *target_type = OBJECT_CLASS(e->data)->type; 283 284 if (type_is_ancestor(target_type, t)) { 285 break; 286 } 287 } 288 289 if (e) { 290 continue; 291 } 292 293 type_initialize_interface(ti, t, t); 294 } 295 } 296 297 ti->class->type = ti; 298 299 while (parent) { 300 if (parent->class_base_init) { 301 parent->class_base_init(ti->class, ti->class_data); 302 } 303 parent = type_get_parent(parent); 304 } 305 306 if (ti->class_init) { 307 ti->class_init(ti->class, ti->class_data); 308 } 309 } 310 311 static void object_init_with_type(Object *obj, TypeImpl *ti) 312 { 313 if (type_has_parent(ti)) { 314 object_init_with_type(obj, type_get_parent(ti)); 315 } 316 317 if (ti->instance_init) { 318 ti->instance_init(obj); 319 } 320 } 321 322 static void object_post_init_with_type(Object *obj, TypeImpl *ti) 323 { 324 if (ti->instance_post_init) { 325 ti->instance_post_init(obj); 326 } 327 328 if (type_has_parent(ti)) { 329 object_post_init_with_type(obj, type_get_parent(ti)); 330 } 331 } 332 333 static void object_property_free(gpointer data) 334 { 335 ObjectProperty *prop = data; 336 337 g_free(prop->name); 338 g_free(prop->type); 339 g_free(prop->description); 340 g_free(prop); 341 } 342 343 void object_initialize_with_type(void *data, size_t size, TypeImpl *type) 344 { 345 Object *obj = data; 346 347 g_assert(type != NULL); 348 type_initialize(type); 349 350 g_assert_cmpint(type->instance_size, >=, sizeof(Object)); 351 g_assert(type->abstract == false); 352 g_assert_cmpint(size, >=, type->instance_size); 353 354 memset(obj, 0, type->instance_size); 355 obj->class = type->class; 356 object_ref(obj); 357 obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, 358 NULL, object_property_free); 359 object_init_with_type(obj, type); 360 object_post_init_with_type(obj, type); 361 } 362 363 void object_initialize(void *data, size_t size, const char *typename) 364 { 365 TypeImpl *type = type_get_by_name(typename); 366 367 object_initialize_with_type(data, size, type); 368 } 369 370 static inline bool object_property_is_child(ObjectProperty *prop) 371 { 372 return strstart(prop->type, "child<", NULL); 373 } 374 375 static void object_property_del_all(Object *obj) 376 { 377 ObjectProperty *prop; 378 GHashTableIter iter; 379 gpointer key, value; 380 bool released; 381 382 do { 383 released = false; 384 g_hash_table_iter_init(&iter, obj->properties); 385 while (g_hash_table_iter_next(&iter, &key, &value)) { 386 prop = value; 387 if (prop->release) { 388 prop->release(obj, prop->name, prop->opaque); 389 prop->release = NULL; 390 released = true; 391 break; 392 } 393 g_hash_table_iter_remove(&iter); 394 } 395 } while (released); 396 397 g_hash_table_unref(obj->properties); 398 } 399 400 static void object_property_del_child(Object *obj, Object *child, Error **errp) 401 { 402 ObjectProperty *prop; 403 GHashTableIter iter; 404 gpointer key, value; 405 406 g_hash_table_iter_init(&iter, obj->properties); 407 while (g_hash_table_iter_next(&iter, &key, &value)) { 408 prop = value; 409 if (object_property_is_child(prop) && prop->opaque == child) { 410 if (prop->release) { 411 prop->release(obj, prop->name, prop->opaque); 412 prop->release = NULL; 413 } 414 break; 415 } 416 } 417 g_hash_table_iter_init(&iter, obj->properties); 418 while (g_hash_table_iter_next(&iter, &key, &value)) { 419 prop = value; 420 if (object_property_is_child(prop) && prop->opaque == child) { 421 g_hash_table_iter_remove(&iter); 422 break; 423 } 424 } 425 } 426 427 void object_unparent(Object *obj) 428 { 429 if (obj->parent) { 430 object_property_del_child(obj->parent, obj, NULL); 431 } 432 } 433 434 static void object_deinit(Object *obj, TypeImpl *type) 435 { 436 if (type->instance_finalize) { 437 type->instance_finalize(obj); 438 } 439 440 if (type_has_parent(type)) { 441 object_deinit(obj, type_get_parent(type)); 442 } 443 } 444 445 static void object_finalize(void *data) 446 { 447 Object *obj = data; 448 TypeImpl *ti = obj->class->type; 449 450 object_property_del_all(obj); 451 object_deinit(obj, ti); 452 453 g_assert_cmpint(obj->ref, ==, 0); 454 if (obj->free) { 455 obj->free(obj); 456 } 457 } 458 459 Object *object_new_with_type(Type type) 460 { 461 Object *obj; 462 463 g_assert(type != NULL); 464 type_initialize(type); 465 466 obj = g_malloc(type->instance_size); 467 object_initialize_with_type(obj, type->instance_size, type); 468 obj->free = g_free; 469 470 return obj; 471 } 472 473 Object *object_new(const char *typename) 474 { 475 TypeImpl *ti = type_get_by_name(typename); 476 477 return object_new_with_type(ti); 478 } 479 480 481 Object *object_new_with_props(const char *typename, 482 Object *parent, 483 const char *id, 484 Error **errp, 485 ...) 486 { 487 va_list vargs; 488 Object *obj; 489 490 va_start(vargs, errp); 491 obj = object_new_with_propv(typename, parent, id, errp, vargs); 492 va_end(vargs); 493 494 return obj; 495 } 496 497 498 Object *object_new_with_propv(const char *typename, 499 Object *parent, 500 const char *id, 501 Error **errp, 502 va_list vargs) 503 { 504 Object *obj; 505 ObjectClass *klass; 506 Error *local_err = NULL; 507 508 klass = object_class_by_name(typename); 509 if (!klass) { 510 error_setg(errp, "invalid object type: %s", typename); 511 return NULL; 512 } 513 514 if (object_class_is_abstract(klass)) { 515 error_setg(errp, "object type '%s' is abstract", typename); 516 return NULL; 517 } 518 obj = object_new(typename); 519 520 if (object_set_propv(obj, &local_err, vargs) < 0) { 521 goto error; 522 } 523 524 object_property_add_child(parent, id, obj, &local_err); 525 if (local_err) { 526 goto error; 527 } 528 529 if (object_dynamic_cast(obj, TYPE_USER_CREATABLE)) { 530 user_creatable_complete(obj, &local_err); 531 if (local_err) { 532 object_unparent(obj); 533 goto error; 534 } 535 } 536 537 object_unref(OBJECT(obj)); 538 return obj; 539 540 error: 541 if (local_err) { 542 error_propagate(errp, local_err); 543 } 544 object_unref(obj); 545 return NULL; 546 } 547 548 549 int object_set_props(Object *obj, 550 Error **errp, 551 ...) 552 { 553 va_list vargs; 554 int ret; 555 556 va_start(vargs, errp); 557 ret = object_set_propv(obj, errp, vargs); 558 va_end(vargs); 559 560 return ret; 561 } 562 563 564 int object_set_propv(Object *obj, 565 Error **errp, 566 va_list vargs) 567 { 568 const char *propname; 569 Error *local_err = NULL; 570 571 propname = va_arg(vargs, char *); 572 while (propname != NULL) { 573 const char *value = va_arg(vargs, char *); 574 575 g_assert(value != NULL); 576 object_property_parse(obj, value, propname, &local_err); 577 if (local_err) { 578 error_propagate(errp, local_err); 579 return -1; 580 } 581 propname = va_arg(vargs, char *); 582 } 583 584 return 0; 585 } 586 587 588 Object *object_dynamic_cast(Object *obj, const char *typename) 589 { 590 if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) { 591 return obj; 592 } 593 594 return NULL; 595 } 596 597 Object *object_dynamic_cast_assert(Object *obj, const char *typename, 598 const char *file, int line, const char *func) 599 { 600 trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)", 601 typename, file, line, func); 602 603 #ifdef CONFIG_QOM_CAST_DEBUG 604 int i; 605 Object *inst; 606 607 for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) { 608 if (obj->class->object_cast_cache[i] == typename) { 609 goto out; 610 } 611 } 612 613 inst = object_dynamic_cast(obj, typename); 614 615 if (!inst && obj) { 616 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 617 file, line, func, obj, typename); 618 abort(); 619 } 620 621 assert(obj == inst); 622 623 if (obj && obj == inst) { 624 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 625 obj->class->object_cast_cache[i - 1] = 626 obj->class->object_cast_cache[i]; 627 } 628 obj->class->object_cast_cache[i - 1] = typename; 629 } 630 631 out: 632 #endif 633 return obj; 634 } 635 636 ObjectClass *object_class_dynamic_cast(ObjectClass *class, 637 const char *typename) 638 { 639 ObjectClass *ret = NULL; 640 TypeImpl *target_type; 641 TypeImpl *type; 642 643 if (!class) { 644 return NULL; 645 } 646 647 /* A simple fast path that can trigger a lot for leaf classes. */ 648 type = class->type; 649 if (type->name == typename) { 650 return class; 651 } 652 653 target_type = type_get_by_name(typename); 654 if (!target_type) { 655 /* target class type unknown, so fail the cast */ 656 return NULL; 657 } 658 659 if (type->class->interfaces && 660 type_is_ancestor(target_type, type_interface)) { 661 int found = 0; 662 GSList *i; 663 664 for (i = class->interfaces; i; i = i->next) { 665 ObjectClass *target_class = i->data; 666 667 if (type_is_ancestor(target_class->type, target_type)) { 668 ret = target_class; 669 found++; 670 } 671 } 672 673 /* The match was ambiguous, don't allow a cast */ 674 if (found > 1) { 675 ret = NULL; 676 } 677 } else if (type_is_ancestor(type, target_type)) { 678 ret = class; 679 } 680 681 return ret; 682 } 683 684 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, 685 const char *typename, 686 const char *file, int line, 687 const char *func) 688 { 689 ObjectClass *ret; 690 691 trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)", 692 typename, file, line, func); 693 694 #ifdef CONFIG_QOM_CAST_DEBUG 695 int i; 696 697 for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) { 698 if (class->class_cast_cache[i] == typename) { 699 ret = class; 700 goto out; 701 } 702 } 703 #else 704 if (!class || !class->interfaces) { 705 return class; 706 } 707 #endif 708 709 ret = object_class_dynamic_cast(class, typename); 710 if (!ret && class) { 711 fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n", 712 file, line, func, class, typename); 713 abort(); 714 } 715 716 #ifdef CONFIG_QOM_CAST_DEBUG 717 if (class && ret == class) { 718 for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { 719 class->class_cast_cache[i - 1] = class->class_cast_cache[i]; 720 } 721 class->class_cast_cache[i - 1] = typename; 722 } 723 out: 724 #endif 725 return ret; 726 } 727 728 const char *object_get_typename(Object *obj) 729 { 730 return obj->class->type->name; 731 } 732 733 ObjectClass *object_get_class(Object *obj) 734 { 735 return obj->class; 736 } 737 738 bool object_class_is_abstract(ObjectClass *klass) 739 { 740 return klass->type->abstract; 741 } 742 743 const char *object_class_get_name(ObjectClass *klass) 744 { 745 return klass->type->name; 746 } 747 748 ObjectClass *object_class_by_name(const char *typename) 749 { 750 TypeImpl *type = type_get_by_name(typename); 751 752 if (!type) { 753 return NULL; 754 } 755 756 type_initialize(type); 757 758 return type->class; 759 } 760 761 ObjectClass *object_class_get_parent(ObjectClass *class) 762 { 763 TypeImpl *type = type_get_parent(class->type); 764 765 if (!type) { 766 return NULL; 767 } 768 769 type_initialize(type); 770 771 return type->class; 772 } 773 774 typedef struct OCFData 775 { 776 void (*fn)(ObjectClass *klass, void *opaque); 777 const char *implements_type; 778 bool include_abstract; 779 void *opaque; 780 } OCFData; 781 782 static void object_class_foreach_tramp(gpointer key, gpointer value, 783 gpointer opaque) 784 { 785 OCFData *data = opaque; 786 TypeImpl *type = value; 787 ObjectClass *k; 788 789 type_initialize(type); 790 k = type->class; 791 792 if (!data->include_abstract && type->abstract) { 793 return; 794 } 795 796 if (data->implements_type && 797 !object_class_dynamic_cast(k, data->implements_type)) { 798 return; 799 } 800 801 data->fn(k, data->opaque); 802 } 803 804 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 805 const char *implements_type, bool include_abstract, 806 void *opaque) 807 { 808 OCFData data = { fn, implements_type, include_abstract, opaque }; 809 810 enumerating_types = true; 811 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); 812 enumerating_types = false; 813 } 814 815 static int do_object_child_foreach(Object *obj, 816 int (*fn)(Object *child, void *opaque), 817 void *opaque, bool recurse) 818 { 819 GHashTableIter iter; 820 ObjectProperty *prop; 821 int ret = 0; 822 823 g_hash_table_iter_init(&iter, obj->properties); 824 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 825 if (object_property_is_child(prop)) { 826 Object *child = prop->opaque; 827 828 ret = fn(child, opaque); 829 if (ret != 0) { 830 break; 831 } 832 if (recurse) { 833 do_object_child_foreach(child, fn, opaque, true); 834 } 835 } 836 } 837 return ret; 838 } 839 840 int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), 841 void *opaque) 842 { 843 return do_object_child_foreach(obj, fn, opaque, false); 844 } 845 846 int object_child_foreach_recursive(Object *obj, 847 int (*fn)(Object *child, void *opaque), 848 void *opaque) 849 { 850 return do_object_child_foreach(obj, fn, opaque, true); 851 } 852 853 static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) 854 { 855 GSList **list = opaque; 856 857 *list = g_slist_prepend(*list, klass); 858 } 859 860 GSList *object_class_get_list(const char *implements_type, 861 bool include_abstract) 862 { 863 GSList *list = NULL; 864 865 object_class_foreach(object_class_get_list_tramp, 866 implements_type, include_abstract, &list); 867 return list; 868 } 869 870 void object_ref(Object *obj) 871 { 872 if (!obj) { 873 return; 874 } 875 atomic_inc(&obj->ref); 876 } 877 878 void object_unref(Object *obj) 879 { 880 if (!obj) { 881 return; 882 } 883 g_assert_cmpint(obj->ref, >, 0); 884 885 /* parent always holds a reference to its children */ 886 if (atomic_fetch_dec(&obj->ref) == 1) { 887 object_finalize(obj); 888 } 889 } 890 891 ObjectProperty * 892 object_property_add(Object *obj, const char *name, const char *type, 893 ObjectPropertyAccessor *get, 894 ObjectPropertyAccessor *set, 895 ObjectPropertyRelease *release, 896 void *opaque, Error **errp) 897 { 898 ObjectProperty *prop; 899 size_t name_len = strlen(name); 900 901 if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) { 902 int i; 903 ObjectProperty *ret; 904 char *name_no_array = g_strdup(name); 905 906 name_no_array[name_len - 3] = '\0'; 907 for (i = 0; ; ++i) { 908 char *full_name = g_strdup_printf("%s[%d]", name_no_array, i); 909 910 ret = object_property_add(obj, full_name, type, get, set, 911 release, opaque, NULL); 912 g_free(full_name); 913 if (ret) { 914 break; 915 } 916 } 917 g_free(name_no_array); 918 return ret; 919 } 920 921 if (g_hash_table_lookup(obj->properties, name) != NULL) { 922 error_setg(errp, "attempt to add duplicate property '%s'" 923 " to object (type '%s')", name, 924 object_get_typename(obj)); 925 return NULL; 926 } 927 928 prop = g_malloc0(sizeof(*prop)); 929 930 prop->name = g_strdup(name); 931 prop->type = g_strdup(type); 932 933 prop->get = get; 934 prop->set = set; 935 prop->release = release; 936 prop->opaque = opaque; 937 938 g_hash_table_insert(obj->properties, prop->name, prop); 939 return prop; 940 } 941 942 ObjectProperty *object_property_find(Object *obj, const char *name, 943 Error **errp) 944 { 945 ObjectProperty *prop; 946 947 prop = g_hash_table_lookup(obj->properties, name); 948 if (prop) { 949 return prop; 950 } 951 952 error_setg(errp, "Property '.%s' not found", name); 953 return NULL; 954 } 955 956 ObjectPropertyIterator *object_property_iter_init(Object *obj) 957 { 958 ObjectPropertyIterator *ret = g_new0(ObjectPropertyIterator, 1); 959 g_hash_table_iter_init(&ret->iter, obj->properties); 960 return ret; 961 } 962 963 void object_property_iter_free(ObjectPropertyIterator *iter) 964 { 965 if (!iter) { 966 return; 967 } 968 g_free(iter); 969 } 970 971 ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter) 972 { 973 gpointer key, val; 974 if (!g_hash_table_iter_next(&iter->iter, &key, &val)) { 975 return NULL; 976 } 977 return val; 978 } 979 980 void object_property_del(Object *obj, const char *name, Error **errp) 981 { 982 ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); 983 984 if (!prop) { 985 error_setg(errp, "Property '.%s' not found", name); 986 return; 987 } 988 989 if (prop->release) { 990 prop->release(obj, name, prop->opaque); 991 } 992 g_hash_table_remove(obj->properties, name); 993 } 994 995 void object_property_get(Object *obj, Visitor *v, const char *name, 996 Error **errp) 997 { 998 ObjectProperty *prop = object_property_find(obj, name, errp); 999 if (prop == NULL) { 1000 return; 1001 } 1002 1003 if (!prop->get) { 1004 error_setg(errp, QERR_PERMISSION_DENIED); 1005 } else { 1006 prop->get(obj, v, prop->opaque, name, errp); 1007 } 1008 } 1009 1010 void object_property_set(Object *obj, Visitor *v, const char *name, 1011 Error **errp) 1012 { 1013 ObjectProperty *prop = object_property_find(obj, name, errp); 1014 if (prop == NULL) { 1015 return; 1016 } 1017 1018 if (!prop->set) { 1019 error_setg(errp, QERR_PERMISSION_DENIED); 1020 } else { 1021 prop->set(obj, v, prop->opaque, name, errp); 1022 } 1023 } 1024 1025 void object_property_set_str(Object *obj, const char *value, 1026 const char *name, Error **errp) 1027 { 1028 QString *qstr = qstring_from_str(value); 1029 object_property_set_qobject(obj, QOBJECT(qstr), name, errp); 1030 1031 QDECREF(qstr); 1032 } 1033 1034 char *object_property_get_str(Object *obj, const char *name, 1035 Error **errp) 1036 { 1037 QObject *ret = object_property_get_qobject(obj, name, errp); 1038 QString *qstring; 1039 char *retval; 1040 1041 if (!ret) { 1042 return NULL; 1043 } 1044 qstring = qobject_to_qstring(ret); 1045 if (!qstring) { 1046 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); 1047 retval = NULL; 1048 } else { 1049 retval = g_strdup(qstring_get_str(qstring)); 1050 } 1051 1052 QDECREF(qstring); 1053 return retval; 1054 } 1055 1056 void object_property_set_link(Object *obj, Object *value, 1057 const char *name, Error **errp) 1058 { 1059 if (value) { 1060 gchar *path = object_get_canonical_path(value); 1061 object_property_set_str(obj, path, name, errp); 1062 g_free(path); 1063 } else { 1064 object_property_set_str(obj, "", name, errp); 1065 } 1066 } 1067 1068 Object *object_property_get_link(Object *obj, const char *name, 1069 Error **errp) 1070 { 1071 char *str = object_property_get_str(obj, name, errp); 1072 Object *target = NULL; 1073 1074 if (str && *str) { 1075 target = object_resolve_path(str, NULL); 1076 if (!target) { 1077 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 1078 "Device '%s' not found", str); 1079 } 1080 } 1081 1082 g_free(str); 1083 return target; 1084 } 1085 1086 void object_property_set_bool(Object *obj, bool value, 1087 const char *name, Error **errp) 1088 { 1089 QBool *qbool = qbool_from_bool(value); 1090 object_property_set_qobject(obj, QOBJECT(qbool), name, errp); 1091 1092 QDECREF(qbool); 1093 } 1094 1095 bool object_property_get_bool(Object *obj, const char *name, 1096 Error **errp) 1097 { 1098 QObject *ret = object_property_get_qobject(obj, name, errp); 1099 QBool *qbool; 1100 bool retval; 1101 1102 if (!ret) { 1103 return false; 1104 } 1105 qbool = qobject_to_qbool(ret); 1106 if (!qbool) { 1107 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean"); 1108 retval = false; 1109 } else { 1110 retval = qbool_get_bool(qbool); 1111 } 1112 1113 QDECREF(qbool); 1114 return retval; 1115 } 1116 1117 void object_property_set_int(Object *obj, int64_t value, 1118 const char *name, Error **errp) 1119 { 1120 QInt *qint = qint_from_int(value); 1121 object_property_set_qobject(obj, QOBJECT(qint), name, errp); 1122 1123 QDECREF(qint); 1124 } 1125 1126 int64_t object_property_get_int(Object *obj, const char *name, 1127 Error **errp) 1128 { 1129 QObject *ret = object_property_get_qobject(obj, name, errp); 1130 QInt *qint; 1131 int64_t retval; 1132 1133 if (!ret) { 1134 return -1; 1135 } 1136 qint = qobject_to_qint(ret); 1137 if (!qint) { 1138 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int"); 1139 retval = -1; 1140 } else { 1141 retval = qint_get_int(qint); 1142 } 1143 1144 QDECREF(qint); 1145 return retval; 1146 } 1147 1148 typedef struct EnumProperty { 1149 const char * const *strings; 1150 int (*get)(Object *, Error **); 1151 void (*set)(Object *, int, Error **); 1152 } EnumProperty; 1153 1154 int object_property_get_enum(Object *obj, const char *name, 1155 const char *typename, Error **errp) 1156 { 1157 Error *err = NULL; 1158 StringOutputVisitor *sov; 1159 StringInputVisitor *siv; 1160 char *str; 1161 int ret; 1162 ObjectProperty *prop = object_property_find(obj, name, errp); 1163 EnumProperty *enumprop; 1164 1165 if (prop == NULL) { 1166 return 0; 1167 } 1168 1169 if (!g_str_equal(prop->type, typename)) { 1170 error_setg(errp, "Property %s on %s is not '%s' enum type", 1171 name, object_class_get_name( 1172 object_get_class(obj)), typename); 1173 return 0; 1174 } 1175 1176 enumprop = prop->opaque; 1177 1178 sov = string_output_visitor_new(false); 1179 object_property_get(obj, string_output_get_visitor(sov), name, &err); 1180 if (err) { 1181 error_propagate(errp, err); 1182 string_output_visitor_cleanup(sov); 1183 return 0; 1184 } 1185 str = string_output_get_string(sov); 1186 siv = string_input_visitor_new(str); 1187 string_output_visitor_cleanup(sov); 1188 visit_type_enum(string_input_get_visitor(siv), 1189 &ret, enumprop->strings, NULL, name, errp); 1190 1191 g_free(str); 1192 string_input_visitor_cleanup(siv); 1193 1194 return ret; 1195 } 1196 1197 void object_property_get_uint16List(Object *obj, const char *name, 1198 uint16List **list, Error **errp) 1199 { 1200 Error *err = NULL; 1201 StringOutputVisitor *ov; 1202 StringInputVisitor *iv; 1203 char *str; 1204 1205 ov = string_output_visitor_new(false); 1206 object_property_get(obj, string_output_get_visitor(ov), 1207 name, &err); 1208 if (err) { 1209 error_propagate(errp, err); 1210 goto out; 1211 } 1212 str = string_output_get_string(ov); 1213 iv = string_input_visitor_new(str); 1214 visit_type_uint16List(string_input_get_visitor(iv), 1215 list, NULL, errp); 1216 1217 g_free(str); 1218 string_input_visitor_cleanup(iv); 1219 out: 1220 string_output_visitor_cleanup(ov); 1221 } 1222 1223 void object_property_parse(Object *obj, const char *string, 1224 const char *name, Error **errp) 1225 { 1226 StringInputVisitor *siv; 1227 siv = string_input_visitor_new(string); 1228 object_property_set(obj, string_input_get_visitor(siv), name, errp); 1229 1230 string_input_visitor_cleanup(siv); 1231 } 1232 1233 char *object_property_print(Object *obj, const char *name, bool human, 1234 Error **errp) 1235 { 1236 StringOutputVisitor *sov; 1237 char *string = NULL; 1238 Error *local_err = NULL; 1239 1240 sov = string_output_visitor_new(human); 1241 object_property_get(obj, string_output_get_visitor(sov), name, &local_err); 1242 if (local_err) { 1243 error_propagate(errp, local_err); 1244 goto out; 1245 } 1246 1247 string = string_output_get_string(sov); 1248 1249 out: 1250 string_output_visitor_cleanup(sov); 1251 return string; 1252 } 1253 1254 const char *object_property_get_type(Object *obj, const char *name, Error **errp) 1255 { 1256 ObjectProperty *prop = object_property_find(obj, name, errp); 1257 if (prop == NULL) { 1258 return NULL; 1259 } 1260 1261 return prop->type; 1262 } 1263 1264 Object *object_get_root(void) 1265 { 1266 static Object *root; 1267 1268 if (!root) { 1269 root = object_new("container"); 1270 } 1271 1272 return root; 1273 } 1274 1275 Object *object_get_objects_root(void) 1276 { 1277 return container_get(object_get_root(), "/objects"); 1278 } 1279 1280 static void object_get_child_property(Object *obj, Visitor *v, void *opaque, 1281 const char *name, Error **errp) 1282 { 1283 Object *child = opaque; 1284 gchar *path; 1285 1286 path = object_get_canonical_path(child); 1287 visit_type_str(v, &path, name, errp); 1288 g_free(path); 1289 } 1290 1291 static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part) 1292 { 1293 return opaque; 1294 } 1295 1296 static void object_finalize_child_property(Object *obj, const char *name, 1297 void *opaque) 1298 { 1299 Object *child = opaque; 1300 1301 if (child->class->unparent) { 1302 (child->class->unparent)(child); 1303 } 1304 child->parent = NULL; 1305 object_unref(child); 1306 } 1307 1308 void object_property_add_child(Object *obj, const char *name, 1309 Object *child, Error **errp) 1310 { 1311 Error *local_err = NULL; 1312 gchar *type; 1313 ObjectProperty *op; 1314 1315 if (child->parent != NULL) { 1316 error_setg(errp, "child object is already parented"); 1317 return; 1318 } 1319 1320 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); 1321 1322 op = object_property_add(obj, name, type, object_get_child_property, NULL, 1323 object_finalize_child_property, child, &local_err); 1324 if (local_err) { 1325 error_propagate(errp, local_err); 1326 goto out; 1327 } 1328 1329 op->resolve = object_resolve_child_property; 1330 object_ref(child); 1331 child->parent = obj; 1332 1333 out: 1334 g_free(type); 1335 } 1336 1337 void object_property_allow_set_link(Object *obj, const char *name, 1338 Object *val, Error **errp) 1339 { 1340 /* Allow the link to be set, always */ 1341 } 1342 1343 typedef struct { 1344 Object **child; 1345 void (*check)(Object *, const char *, Object *, Error **); 1346 ObjectPropertyLinkFlags flags; 1347 } LinkProperty; 1348 1349 static void object_get_link_property(Object *obj, Visitor *v, void *opaque, 1350 const char *name, Error **errp) 1351 { 1352 LinkProperty *lprop = opaque; 1353 Object **child = lprop->child; 1354 gchar *path; 1355 1356 if (*child) { 1357 path = object_get_canonical_path(*child); 1358 visit_type_str(v, &path, name, errp); 1359 g_free(path); 1360 } else { 1361 path = (gchar *)""; 1362 visit_type_str(v, &path, name, errp); 1363 } 1364 } 1365 1366 /* 1367 * object_resolve_link: 1368 * 1369 * Lookup an object and ensure its type matches the link property type. This 1370 * is similar to object_resolve_path() except type verification against the 1371 * link property is performed. 1372 * 1373 * Returns: The matched object or NULL on path lookup failures. 1374 */ 1375 static Object *object_resolve_link(Object *obj, const char *name, 1376 const char *path, Error **errp) 1377 { 1378 const char *type; 1379 gchar *target_type; 1380 bool ambiguous = false; 1381 Object *target; 1382 1383 /* Go from link<FOO> to FOO. */ 1384 type = object_property_get_type(obj, name, NULL); 1385 target_type = g_strndup(&type[5], strlen(type) - 6); 1386 target = object_resolve_path_type(path, target_type, &ambiguous); 1387 1388 if (ambiguous) { 1389 error_setg(errp, "Path '%s' does not uniquely identify an object", 1390 path); 1391 } else if (!target) { 1392 target = object_resolve_path(path, &ambiguous); 1393 if (target || ambiguous) { 1394 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type); 1395 } else { 1396 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 1397 "Device '%s' not found", path); 1398 } 1399 target = NULL; 1400 } 1401 g_free(target_type); 1402 1403 return target; 1404 } 1405 1406 static void object_set_link_property(Object *obj, Visitor *v, void *opaque, 1407 const char *name, Error **errp) 1408 { 1409 Error *local_err = NULL; 1410 LinkProperty *prop = opaque; 1411 Object **child = prop->child; 1412 Object *old_target = *child; 1413 Object *new_target = NULL; 1414 char *path = NULL; 1415 1416 visit_type_str(v, &path, name, &local_err); 1417 1418 if (!local_err && strcmp(path, "") != 0) { 1419 new_target = object_resolve_link(obj, name, path, &local_err); 1420 } 1421 1422 g_free(path); 1423 if (local_err) { 1424 error_propagate(errp, local_err); 1425 return; 1426 } 1427 1428 prop->check(obj, name, new_target, &local_err); 1429 if (local_err) { 1430 error_propagate(errp, local_err); 1431 return; 1432 } 1433 1434 object_ref(new_target); 1435 *child = new_target; 1436 object_unref(old_target); 1437 } 1438 1439 static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part) 1440 { 1441 LinkProperty *lprop = opaque; 1442 1443 return *lprop->child; 1444 } 1445 1446 static void object_release_link_property(Object *obj, const char *name, 1447 void *opaque) 1448 { 1449 LinkProperty *prop = opaque; 1450 1451 if ((prop->flags & OBJ_PROP_LINK_UNREF_ON_RELEASE) && *prop->child) { 1452 object_unref(*prop->child); 1453 } 1454 g_free(prop); 1455 } 1456 1457 void object_property_add_link(Object *obj, const char *name, 1458 const char *type, Object **child, 1459 void (*check)(Object *, const char *, 1460 Object *, Error **), 1461 ObjectPropertyLinkFlags flags, 1462 Error **errp) 1463 { 1464 Error *local_err = NULL; 1465 LinkProperty *prop = g_malloc(sizeof(*prop)); 1466 gchar *full_type; 1467 ObjectProperty *op; 1468 1469 prop->child = child; 1470 prop->check = check; 1471 prop->flags = flags; 1472 1473 full_type = g_strdup_printf("link<%s>", type); 1474 1475 op = object_property_add(obj, name, full_type, 1476 object_get_link_property, 1477 check ? object_set_link_property : NULL, 1478 object_release_link_property, 1479 prop, 1480 &local_err); 1481 if (local_err) { 1482 error_propagate(errp, local_err); 1483 g_free(prop); 1484 goto out; 1485 } 1486 1487 op->resolve = object_resolve_link_property; 1488 1489 out: 1490 g_free(full_type); 1491 } 1492 1493 void object_property_add_const_link(Object *obj, const char *name, 1494 Object *target, Error **errp) 1495 { 1496 char *link_type; 1497 ObjectProperty *op; 1498 1499 link_type = g_strdup_printf("link<%s>", object_get_typename(target)); 1500 op = object_property_add(obj, name, link_type, 1501 object_get_child_property, NULL, 1502 NULL, target, errp); 1503 if (op != NULL) { 1504 op->resolve = object_resolve_child_property; 1505 } 1506 g_free(link_type); 1507 } 1508 1509 gchar *object_get_canonical_path_component(Object *obj) 1510 { 1511 ObjectProperty *prop = NULL; 1512 GHashTableIter iter; 1513 1514 g_assert(obj); 1515 g_assert(obj->parent != NULL); 1516 1517 g_hash_table_iter_init(&iter, obj->parent->properties); 1518 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 1519 if (!object_property_is_child(prop)) { 1520 continue; 1521 } 1522 1523 if (prop->opaque == obj) { 1524 return g_strdup(prop->name); 1525 } 1526 } 1527 1528 /* obj had a parent but was not a child, should never happen */ 1529 g_assert_not_reached(); 1530 return NULL; 1531 } 1532 1533 gchar *object_get_canonical_path(Object *obj) 1534 { 1535 Object *root = object_get_root(); 1536 char *newpath, *path = NULL; 1537 1538 while (obj != root) { 1539 char *component = object_get_canonical_path_component(obj); 1540 1541 if (path) { 1542 newpath = g_strdup_printf("%s/%s", component, path); 1543 g_free(component); 1544 g_free(path); 1545 path = newpath; 1546 } else { 1547 path = component; 1548 } 1549 1550 obj = obj->parent; 1551 } 1552 1553 newpath = g_strdup_printf("/%s", path ? path : ""); 1554 g_free(path); 1555 1556 return newpath; 1557 } 1558 1559 Object *object_resolve_path_component(Object *parent, const gchar *part) 1560 { 1561 ObjectProperty *prop = object_property_find(parent, part, NULL); 1562 if (prop == NULL) { 1563 return NULL; 1564 } 1565 1566 if (prop->resolve) { 1567 return prop->resolve(parent, prop->opaque, part); 1568 } else { 1569 return NULL; 1570 } 1571 } 1572 1573 static Object *object_resolve_abs_path(Object *parent, 1574 gchar **parts, 1575 const char *typename, 1576 int index) 1577 { 1578 Object *child; 1579 1580 if (parts[index] == NULL) { 1581 return object_dynamic_cast(parent, typename); 1582 } 1583 1584 if (strcmp(parts[index], "") == 0) { 1585 return object_resolve_abs_path(parent, parts, typename, index + 1); 1586 } 1587 1588 child = object_resolve_path_component(parent, parts[index]); 1589 if (!child) { 1590 return NULL; 1591 } 1592 1593 return object_resolve_abs_path(child, parts, typename, index + 1); 1594 } 1595 1596 static Object *object_resolve_partial_path(Object *parent, 1597 gchar **parts, 1598 const char *typename, 1599 bool *ambiguous) 1600 { 1601 Object *obj; 1602 GHashTableIter iter; 1603 ObjectProperty *prop; 1604 1605 obj = object_resolve_abs_path(parent, parts, typename, 0); 1606 1607 g_hash_table_iter_init(&iter, parent->properties); 1608 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { 1609 Object *found; 1610 1611 if (!object_property_is_child(prop)) { 1612 continue; 1613 } 1614 1615 found = object_resolve_partial_path(prop->opaque, parts, 1616 typename, ambiguous); 1617 if (found) { 1618 if (obj) { 1619 if (ambiguous) { 1620 *ambiguous = true; 1621 } 1622 return NULL; 1623 } 1624 obj = found; 1625 } 1626 1627 if (ambiguous && *ambiguous) { 1628 return NULL; 1629 } 1630 } 1631 1632 return obj; 1633 } 1634 1635 Object *object_resolve_path_type(const char *path, const char *typename, 1636 bool *ambiguous) 1637 { 1638 Object *obj; 1639 gchar **parts; 1640 1641 parts = g_strsplit(path, "/", 0); 1642 assert(parts); 1643 1644 if (parts[0] == NULL || strcmp(parts[0], "") != 0) { 1645 if (ambiguous) { 1646 *ambiguous = false; 1647 } 1648 obj = object_resolve_partial_path(object_get_root(), parts, 1649 typename, ambiguous); 1650 } else { 1651 obj = object_resolve_abs_path(object_get_root(), parts, typename, 1); 1652 } 1653 1654 g_strfreev(parts); 1655 1656 return obj; 1657 } 1658 1659 Object *object_resolve_path(const char *path, bool *ambiguous) 1660 { 1661 return object_resolve_path_type(path, TYPE_OBJECT, ambiguous); 1662 } 1663 1664 typedef struct StringProperty 1665 { 1666 char *(*get)(Object *, Error **); 1667 void (*set)(Object *, const char *, Error **); 1668 } StringProperty; 1669 1670 static void property_get_str(Object *obj, Visitor *v, void *opaque, 1671 const char *name, Error **errp) 1672 { 1673 StringProperty *prop = opaque; 1674 char *value; 1675 Error *err = NULL; 1676 1677 value = prop->get(obj, &err); 1678 if (err) { 1679 error_propagate(errp, err); 1680 return; 1681 } 1682 1683 visit_type_str(v, &value, name, errp); 1684 g_free(value); 1685 } 1686 1687 static void property_set_str(Object *obj, Visitor *v, void *opaque, 1688 const char *name, Error **errp) 1689 { 1690 StringProperty *prop = opaque; 1691 char *value; 1692 Error *local_err = NULL; 1693 1694 visit_type_str(v, &value, name, &local_err); 1695 if (local_err) { 1696 error_propagate(errp, local_err); 1697 return; 1698 } 1699 1700 prop->set(obj, value, errp); 1701 g_free(value); 1702 } 1703 1704 static void property_release_str(Object *obj, const char *name, 1705 void *opaque) 1706 { 1707 StringProperty *prop = opaque; 1708 g_free(prop); 1709 } 1710 1711 void object_property_add_str(Object *obj, const char *name, 1712 char *(*get)(Object *, Error **), 1713 void (*set)(Object *, const char *, Error **), 1714 Error **errp) 1715 { 1716 Error *local_err = NULL; 1717 StringProperty *prop = g_malloc0(sizeof(*prop)); 1718 1719 prop->get = get; 1720 prop->set = set; 1721 1722 object_property_add(obj, name, "string", 1723 get ? property_get_str : NULL, 1724 set ? property_set_str : NULL, 1725 property_release_str, 1726 prop, &local_err); 1727 if (local_err) { 1728 error_propagate(errp, local_err); 1729 g_free(prop); 1730 } 1731 } 1732 1733 typedef struct BoolProperty 1734 { 1735 bool (*get)(Object *, Error **); 1736 void (*set)(Object *, bool, Error **); 1737 } BoolProperty; 1738 1739 static void property_get_bool(Object *obj, Visitor *v, void *opaque, 1740 const char *name, Error **errp) 1741 { 1742 BoolProperty *prop = opaque; 1743 bool value; 1744 Error *err = NULL; 1745 1746 value = prop->get(obj, &err); 1747 if (err) { 1748 error_propagate(errp, err); 1749 return; 1750 } 1751 1752 visit_type_bool(v, &value, name, errp); 1753 } 1754 1755 static void property_set_bool(Object *obj, Visitor *v, void *opaque, 1756 const char *name, Error **errp) 1757 { 1758 BoolProperty *prop = opaque; 1759 bool value; 1760 Error *local_err = NULL; 1761 1762 visit_type_bool(v, &value, name, &local_err); 1763 if (local_err) { 1764 error_propagate(errp, local_err); 1765 return; 1766 } 1767 1768 prop->set(obj, value, errp); 1769 } 1770 1771 static void property_release_bool(Object *obj, const char *name, 1772 void *opaque) 1773 { 1774 BoolProperty *prop = opaque; 1775 g_free(prop); 1776 } 1777 1778 void object_property_add_bool(Object *obj, const char *name, 1779 bool (*get)(Object *, Error **), 1780 void (*set)(Object *, bool, Error **), 1781 Error **errp) 1782 { 1783 Error *local_err = NULL; 1784 BoolProperty *prop = g_malloc0(sizeof(*prop)); 1785 1786 prop->get = get; 1787 prop->set = set; 1788 1789 object_property_add(obj, name, "bool", 1790 get ? property_get_bool : NULL, 1791 set ? property_set_bool : NULL, 1792 property_release_bool, 1793 prop, &local_err); 1794 if (local_err) { 1795 error_propagate(errp, local_err); 1796 g_free(prop); 1797 } 1798 } 1799 1800 static void property_get_enum(Object *obj, Visitor *v, void *opaque, 1801 const char *name, Error **errp) 1802 { 1803 EnumProperty *prop = opaque; 1804 int value; 1805 Error *err = NULL; 1806 1807 value = prop->get(obj, &err); 1808 if (err) { 1809 error_propagate(errp, err); 1810 return; 1811 } 1812 1813 visit_type_enum(v, &value, prop->strings, NULL, name, errp); 1814 } 1815 1816 static void property_set_enum(Object *obj, Visitor *v, void *opaque, 1817 const char *name, Error **errp) 1818 { 1819 EnumProperty *prop = opaque; 1820 int value; 1821 Error *err = NULL; 1822 1823 visit_type_enum(v, &value, prop->strings, NULL, name, &err); 1824 if (err) { 1825 error_propagate(errp, err); 1826 return; 1827 } 1828 prop->set(obj, value, errp); 1829 } 1830 1831 static void property_release_enum(Object *obj, const char *name, 1832 void *opaque) 1833 { 1834 EnumProperty *prop = opaque; 1835 g_free(prop); 1836 } 1837 1838 void object_property_add_enum(Object *obj, const char *name, 1839 const char *typename, 1840 const char * const *strings, 1841 int (*get)(Object *, Error **), 1842 void (*set)(Object *, int, Error **), 1843 Error **errp) 1844 { 1845 Error *local_err = NULL; 1846 EnumProperty *prop = g_malloc(sizeof(*prop)); 1847 1848 prop->strings = strings; 1849 prop->get = get; 1850 prop->set = set; 1851 1852 object_property_add(obj, name, typename, 1853 get ? property_get_enum : NULL, 1854 set ? property_set_enum : NULL, 1855 property_release_enum, 1856 prop, &local_err); 1857 if (local_err) { 1858 error_propagate(errp, local_err); 1859 g_free(prop); 1860 } 1861 } 1862 1863 typedef struct TMProperty { 1864 void (*get)(Object *, struct tm *, Error **); 1865 } TMProperty; 1866 1867 static void property_get_tm(Object *obj, Visitor *v, void *opaque, 1868 const char *name, Error **errp) 1869 { 1870 TMProperty *prop = opaque; 1871 Error *err = NULL; 1872 struct tm value; 1873 1874 prop->get(obj, &value, &err); 1875 if (err) { 1876 goto out; 1877 } 1878 1879 visit_start_struct(v, NULL, "struct tm", name, 0, &err); 1880 if (err) { 1881 goto out; 1882 } 1883 visit_type_int32(v, &value.tm_year, "tm_year", &err); 1884 if (err) { 1885 goto out_end; 1886 } 1887 visit_type_int32(v, &value.tm_mon, "tm_mon", &err); 1888 if (err) { 1889 goto out_end; 1890 } 1891 visit_type_int32(v, &value.tm_mday, "tm_mday", &err); 1892 if (err) { 1893 goto out_end; 1894 } 1895 visit_type_int32(v, &value.tm_hour, "tm_hour", &err); 1896 if (err) { 1897 goto out_end; 1898 } 1899 visit_type_int32(v, &value.tm_min, "tm_min", &err); 1900 if (err) { 1901 goto out_end; 1902 } 1903 visit_type_int32(v, &value.tm_sec, "tm_sec", &err); 1904 if (err) { 1905 goto out_end; 1906 } 1907 out_end: 1908 error_propagate(errp, err); 1909 err = NULL; 1910 visit_end_struct(v, errp); 1911 out: 1912 error_propagate(errp, err); 1913 1914 } 1915 1916 static void property_release_tm(Object *obj, const char *name, 1917 void *opaque) 1918 { 1919 TMProperty *prop = opaque; 1920 g_free(prop); 1921 } 1922 1923 void object_property_add_tm(Object *obj, const char *name, 1924 void (*get)(Object *, struct tm *, Error **), 1925 Error **errp) 1926 { 1927 Error *local_err = NULL; 1928 TMProperty *prop = g_malloc0(sizeof(*prop)); 1929 1930 prop->get = get; 1931 1932 object_property_add(obj, name, "struct tm", 1933 get ? property_get_tm : NULL, NULL, 1934 property_release_tm, 1935 prop, &local_err); 1936 if (local_err) { 1937 error_propagate(errp, local_err); 1938 g_free(prop); 1939 } 1940 } 1941 1942 static char *qdev_get_type(Object *obj, Error **errp) 1943 { 1944 return g_strdup(object_get_typename(obj)); 1945 } 1946 1947 static void property_get_uint8_ptr(Object *obj, Visitor *v, 1948 void *opaque, const char *name, 1949 Error **errp) 1950 { 1951 uint8_t value = *(uint8_t *)opaque; 1952 visit_type_uint8(v, &value, name, errp); 1953 } 1954 1955 static void property_get_uint16_ptr(Object *obj, Visitor *v, 1956 void *opaque, const char *name, 1957 Error **errp) 1958 { 1959 uint16_t value = *(uint16_t *)opaque; 1960 visit_type_uint16(v, &value, name, errp); 1961 } 1962 1963 static void property_get_uint32_ptr(Object *obj, Visitor *v, 1964 void *opaque, const char *name, 1965 Error **errp) 1966 { 1967 uint32_t value = *(uint32_t *)opaque; 1968 visit_type_uint32(v, &value, name, errp); 1969 } 1970 1971 static void property_get_uint64_ptr(Object *obj, Visitor *v, 1972 void *opaque, const char *name, 1973 Error **errp) 1974 { 1975 uint64_t value = *(uint64_t *)opaque; 1976 visit_type_uint64(v, &value, name, errp); 1977 } 1978 1979 void object_property_add_uint8_ptr(Object *obj, const char *name, 1980 const uint8_t *v, Error **errp) 1981 { 1982 object_property_add(obj, name, "uint8", property_get_uint8_ptr, 1983 NULL, NULL, (void *)v, errp); 1984 } 1985 1986 void object_property_add_uint16_ptr(Object *obj, const char *name, 1987 const uint16_t *v, Error **errp) 1988 { 1989 object_property_add(obj, name, "uint16", property_get_uint16_ptr, 1990 NULL, NULL, (void *)v, errp); 1991 } 1992 1993 void object_property_add_uint32_ptr(Object *obj, const char *name, 1994 const uint32_t *v, Error **errp) 1995 { 1996 object_property_add(obj, name, "uint32", property_get_uint32_ptr, 1997 NULL, NULL, (void *)v, errp); 1998 } 1999 2000 void object_property_add_uint64_ptr(Object *obj, const char *name, 2001 const uint64_t *v, Error **errp) 2002 { 2003 object_property_add(obj, name, "uint64", property_get_uint64_ptr, 2004 NULL, NULL, (void *)v, errp); 2005 } 2006 2007 typedef struct { 2008 Object *target_obj; 2009 char *target_name; 2010 } AliasProperty; 2011 2012 static void property_get_alias(Object *obj, struct Visitor *v, void *opaque, 2013 const char *name, Error **errp) 2014 { 2015 AliasProperty *prop = opaque; 2016 2017 object_property_get(prop->target_obj, v, prop->target_name, errp); 2018 } 2019 2020 static void property_set_alias(Object *obj, struct Visitor *v, void *opaque, 2021 const char *name, Error **errp) 2022 { 2023 AliasProperty *prop = opaque; 2024 2025 object_property_set(prop->target_obj, v, prop->target_name, errp); 2026 } 2027 2028 static Object *property_resolve_alias(Object *obj, void *opaque, 2029 const gchar *part) 2030 { 2031 AliasProperty *prop = opaque; 2032 2033 return object_resolve_path_component(prop->target_obj, prop->target_name); 2034 } 2035 2036 static void property_release_alias(Object *obj, const char *name, void *opaque) 2037 { 2038 AliasProperty *prop = opaque; 2039 2040 g_free(prop->target_name); 2041 g_free(prop); 2042 } 2043 2044 void object_property_add_alias(Object *obj, const char *name, 2045 Object *target_obj, const char *target_name, 2046 Error **errp) 2047 { 2048 AliasProperty *prop; 2049 ObjectProperty *op; 2050 ObjectProperty *target_prop; 2051 gchar *prop_type; 2052 Error *local_err = NULL; 2053 2054 target_prop = object_property_find(target_obj, target_name, errp); 2055 if (!target_prop) { 2056 return; 2057 } 2058 2059 if (object_property_is_child(target_prop)) { 2060 prop_type = g_strdup_printf("link%s", 2061 target_prop->type + strlen("child")); 2062 } else { 2063 prop_type = g_strdup(target_prop->type); 2064 } 2065 2066 prop = g_malloc(sizeof(*prop)); 2067 prop->target_obj = target_obj; 2068 prop->target_name = g_strdup(target_name); 2069 2070 op = object_property_add(obj, name, prop_type, 2071 property_get_alias, 2072 property_set_alias, 2073 property_release_alias, 2074 prop, &local_err); 2075 if (local_err) { 2076 error_propagate(errp, local_err); 2077 g_free(prop); 2078 goto out; 2079 } 2080 op->resolve = property_resolve_alias; 2081 2082 object_property_set_description(obj, op->name, 2083 target_prop->description, 2084 &error_abort); 2085 2086 out: 2087 g_free(prop_type); 2088 } 2089 2090 void object_property_set_description(Object *obj, const char *name, 2091 const char *description, Error **errp) 2092 { 2093 ObjectProperty *op; 2094 2095 op = object_property_find(obj, name, errp); 2096 if (!op) { 2097 return; 2098 } 2099 2100 g_free(op->description); 2101 op->description = g_strdup(description); 2102 } 2103 2104 static void object_instance_init(Object *obj) 2105 { 2106 object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); 2107 } 2108 2109 static void register_types(void) 2110 { 2111 static TypeInfo interface_info = { 2112 .name = TYPE_INTERFACE, 2113 .class_size = sizeof(InterfaceClass), 2114 .abstract = true, 2115 }; 2116 2117 static TypeInfo object_info = { 2118 .name = TYPE_OBJECT, 2119 .instance_size = sizeof(Object), 2120 .instance_init = object_instance_init, 2121 .abstract = true, 2122 }; 2123 2124 type_interface = type_register_internal(&interface_info); 2125 type_register_internal(&object_info); 2126 } 2127 2128 type_init(register_types) 2129