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