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