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