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