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