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