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