1 /* 2 * Copyright (c) 2010 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Adam Hamsik. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/types.h> 31 #include <sys/param.h> 32 #include <sys/ioctl.h> 33 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include <prop/proplib.h> 42 43 #include <dev/dm/netbsd-dm.h> 44 45 #include "dm.h" 46 47 /* 48 * Libdm library works like interface between device-mapper driver and 49 * NetBSD userspace. For start it uses same set of commands like linux 50 * libdevmapper, but in later stage if we introduce NetBSD device-mapper 51 * extensions we don't need to change libdevmapper. 52 * 53 * LIBDM basically creates one proplib dictionary with everything what is 54 * needed to work with device-mapper devices. 55 * 56 * Basic element of libdm is libdm_task which contains version and command 57 * string with another dictionary cmd. 58 */ 59 60 struct libdm_cmd { 61 prop_array_t ldm_cmd; 62 }; 63 64 struct libdm_iter { 65 prop_object_iterator_t ldm_obji; 66 }; 67 68 struct libdm_task { 69 prop_dictionary_t ldm_task; 70 }; 71 72 struct libdm_table { 73 prop_dictionary_t ldm_tbl; 74 }; 75 76 struct libdm_target { 77 prop_dictionary_t ldm_trgt; 78 }; 79 80 struct libdm_dev { 81 prop_dictionary_t ldm_dev; 82 }; 83 84 struct cmd_version cmd_ver[] = { 85 {"version", {4, 0, 0}}, 86 {"targets", {4, 0, 0}}, 87 {"create", {4, 0, 0}}, 88 {"info", {4, 0, 0}}, 89 {"mknodes",{4, 0, 0}}, 90 {"names", {4, 0, 0}}, 91 {"suspend",{4, 0, 0}}, 92 {"remove", {4, 0, 0}}, 93 {"rename", {4, 0, 0}}, 94 {"resume", {4, 0, 0}}, 95 {"clear", {4, 0, 0}}, 96 {"deps", {4, 0, 0}}, 97 {"reload", {4, 0, 0}}, 98 {"status", {4, 0, 0}}, 99 {"table", {4, 0, 0}}, 100 /* NetBSD device-mapper command extension goes here */ 101 {NULL, {0, 0, 0}} 102 }; 103 104 /* /dev/mapper/control managing routines */ 105 static int libdm_control_open(const char *); 106 static int libdm_control_close(int); 107 108 static int 109 libdm_control_open(const char *path) 110 { 111 int fd; 112 #ifdef RUMP_ACTION 113 if ((fd = rump_sys_open(path, O_RDWR)) < 0) 114 return -1; 115 #else 116 if ((fd = open(path, O_RDWR)) < 0) 117 return -1; 118 #endif 119 return fd; 120 } 121 122 static int 123 libdm_control_close(int fd) 124 { 125 126 #ifdef RUMP_ACTION 127 return rump_sys_close(fd); 128 #else 129 return close(fd); 130 #endif 131 } 132 133 /* Destroy iterator for arrays such as version strings, cmd_data. */ 134 void 135 libdm_iter_destroy(libdm_iter_t libdm_iter) 136 { 137 138 prop_object_iterator_release(libdm_iter->ldm_obji); 139 free(libdm_iter); 140 } 141 142 /* 143 * Issue ioctl call to kernel, releasing both dictionaries is 144 * left on callers. 145 */ 146 int 147 libdm_task_run(libdm_task_t libdm_task) 148 { 149 prop_dictionary_t dict; 150 int libdm_control_fd = -1; 151 int error; 152 #ifdef RUMP_ACTION 153 struct plistref prefp; 154 #endif 155 error = 0; 156 157 if (libdm_task == NULL) 158 return ENOENT; 159 160 if ((libdm_control_fd = libdm_control_open(DM_DEVICE_PATH)) < 0) 161 return errno; 162 #ifdef RUMP_ACTION 163 prop_dictionary_externalize_to_pref(libdm_task->ldm_task, 164 &prefp); 165 166 error = rump_sys_ioctl(libdm_control_fd, NETBSD_DM_IOCTL, &prefp); 167 if (error < 0) { 168 libdm_task_destroy(libdm_task); 169 libdm_task = NULL; 170 libdm_control_close(libdm_control_fd); 171 172 return error; 173 } 174 dict = prop_dictionary_internalize(prefp.pref_plist); 175 #else 176 prop_dictionary_externalize_to_file(libdm_task->ldm_task, "/tmp/libdm_in"); 177 error = prop_dictionary_sendrecv_ioctl(libdm_task->ldm_task, 178 libdm_control_fd, NETBSD_DM_IOCTL, &dict); 179 if ( error != 0) { 180 libdm_task_destroy(libdm_task); 181 libdm_task = NULL; 182 libdm_control_close(libdm_control_fd); 183 return error; 184 } 185 prop_dictionary_externalize_to_file(dict, "/tmp/libdm_out"); 186 #endif 187 188 libdm_control_close(libdm_control_fd); 189 prop_object_retain(dict); 190 prop_object_release(libdm_task->ldm_task); 191 libdm_task->ldm_task = dict; 192 193 return EXIT_SUCCESS; 194 } 195 196 197 /* Create libdm General task structure */ 198 libdm_task_t 199 libdm_task_create(const char *command) 200 { 201 libdm_task_t task; 202 size_t i,len,slen; 203 prop_array_t ver; 204 205 task = NULL; 206 207 task = malloc(sizeof(*task)); 208 if (task == NULL) 209 return NULL; 210 211 if ((task->ldm_task = prop_dictionary_create()) == NULL) { 212 free(task); 213 return NULL; 214 } 215 216 if ((prop_dictionary_set_cstring(task->ldm_task, DM_IOCTL_COMMAND, 217 command)) == false) { 218 prop_object_release(task->ldm_task); 219 free(task); 220 return NULL; 221 } 222 223 len = strlen(command); 224 225 for (i = 0; cmd_ver[i].cmd != NULL; i++) { 226 slen = strlen(cmd_ver[i].cmd); 227 228 if (len != slen) 229 continue; 230 231 if ((strncmp(command, cmd_ver[i].cmd, slen)) == 0) { 232 ver = prop_array_create(); 233 prop_array_add_uint32(ver, cmd_ver[i].version[0]); 234 prop_array_add_uint32(ver, cmd_ver[i].version[1]); 235 prop_array_add_uint32(ver, cmd_ver[i].version[2]); 236 237 prop_dictionary_set(task->ldm_task, DM_IOCTL_VERSION, 238 ver); 239 240 prop_object_release(ver); 241 break; 242 } 243 } 244 245 return task; 246 } 247 248 void 249 libdm_task_destroy(libdm_task_t libdm_task) 250 { 251 252 if (libdm_task != NULL) 253 prop_object_release(libdm_task->ldm_task); 254 free(libdm_task); 255 } 256 257 /* Set device name */ 258 int 259 libdm_task_set_name(const char *name, libdm_task_t libdm_task) 260 { 261 262 if ((prop_dictionary_set_cstring(libdm_task->ldm_task, 263 DM_IOCTL_NAME, name)) == false) 264 return ENOENT; 265 266 return 0; 267 } 268 269 /* Set device name */ 270 char * 271 libdm_task_get_name(libdm_task_t libdm_task) 272 { 273 char *name; 274 275 if (!prop_dictionary_get_cstring_nocopy(libdm_task->ldm_task, 276 DM_IOCTL_NAME, (const char **)&name)) 277 return NULL; 278 279 return name; 280 } 281 282 /* Set device uuid */ 283 int 284 libdm_task_set_uuid(const char *uuid, libdm_task_t libdm_task) 285 { 286 287 if ((prop_dictionary_set_cstring(libdm_task->ldm_task, 288 DM_IOCTL_UUID, uuid)) == false) 289 return ENOENT; 290 291 return 0; 292 } 293 294 /* Set device name */ 295 char * 296 libdm_task_get_uuid(libdm_task_t libdm_task) 297 { 298 char *uuid; 299 300 if (!prop_dictionary_get_cstring_nocopy(libdm_task->ldm_task, 301 DM_IOCTL_UUID, (const char **)&uuid)) 302 return NULL; 303 304 return uuid; 305 } 306 307 /* Get command name */ 308 char * 309 libdm_task_get_command(libdm_task_t libdm_task) 310 { 311 char *command; 312 313 if (!prop_dictionary_get_cstring_nocopy(libdm_task->ldm_task, 314 DM_IOCTL_COMMAND, (const char **)&command)) 315 return NULL; 316 317 return command; 318 } 319 320 int32_t 321 libdm_task_get_cmd_version(libdm_task_t libdm_task, uint32_t *ver, size_t size) 322 { 323 prop_array_t prop_ver; 324 size_t i; 325 326 prop_ver = prop_dictionary_get(libdm_task->ldm_task, 327 DM_IOCTL_VERSION); 328 329 i = prop_array_count(prop_ver); 330 331 if (i > size) 332 return -i; 333 334 for (i = 0; i < size; i++) 335 prop_array_get_uint32(prop_ver, i, &ver[i]); 336 337 return i; 338 } 339 340 /* Select device minor number. */ 341 int 342 libdm_task_set_minor(uint32_t minor, libdm_task_t libdm_task) 343 { 344 345 if ((prop_dictionary_set_uint32(libdm_task->ldm_task, 346 DM_IOCTL_MINOR, minor)) == false) 347 return ENOENT; 348 349 return 0; 350 } 351 352 /* Select device minor number. */ 353 uint32_t 354 libdm_task_get_minor(libdm_task_t libdm_task) 355 { 356 uint32_t minor; 357 358 minor = 0; 359 360 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 361 DM_IOCTL_MINOR, &minor); 362 363 return minor; 364 } 365 366 /* Set/Del DM_SUSPEND_FLAG for caller. */ 367 void 368 libdm_task_set_suspend_flag(libdm_task_t libdm_task) 369 { 370 uint32_t flags; 371 372 flags = 0; 373 374 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 375 DM_IOCTL_FLAGS, &flags); 376 377 flags |= DM_SUSPEND_FLAG; 378 379 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 380 DM_IOCTL_FLAGS, flags); 381 } 382 383 void 384 libdm_task_del_suspend_flag(libdm_task_t libdm_task) 385 { 386 uint32_t flags; 387 388 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 389 DM_IOCTL_FLAGS, &flags); 390 391 flags &= ~DM_SUSPEND_FLAG; 392 393 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 394 DM_IOCTL_FLAGS, flags); 395 } 396 397 /* Set/Del DM_STATUS_FLAG for caller. */ 398 void 399 libdm_task_set_status_flag(libdm_task_t libdm_task) 400 { 401 uint32_t flags; 402 403 flags = 0; 404 405 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 406 DM_IOCTL_FLAGS, &flags); 407 408 flags |= DM_STATUS_TABLE_FLAG; 409 410 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 411 DM_IOCTL_FLAGS, flags); 412 } 413 414 void 415 libdm_task_del_status_flag(libdm_task_t libdm_task) 416 { 417 uint32_t flags; 418 419 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 420 DM_IOCTL_FLAGS, &flags); 421 422 flags &= ~DM_STATUS_TABLE_FLAG; 423 424 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 425 DM_IOCTL_FLAGS, flags); 426 } 427 428 /* Set/Del DM_EXISTS_FLAG for caller. */ 429 void 430 libdm_task_set_exists_flag(libdm_task_t libdm_task) 431 { 432 uint32_t flags; 433 434 flags = 0; 435 436 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 437 DM_IOCTL_FLAGS, &flags); 438 439 flags |= DM_EXISTS_FLAG; 440 441 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 442 DM_IOCTL_FLAGS, flags); 443 } 444 445 void 446 libdm_task_del_exists_flag(libdm_task_t libdm_task) 447 { 448 uint32_t flags; 449 450 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 451 DM_IOCTL_FLAGS, &flags); 452 453 flags &= ~DM_EXISTS_FLAG; 454 455 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 456 DM_IOCTL_FLAGS, flags); 457 } 458 459 /* Set flags used by LVM this is shortcut and should not be used 460 by anyone else. */ 461 void 462 libdm_task_set_flags(libdm_task_t libdm_task, uint32_t flags) 463 { 464 465 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 466 DM_IOCTL_FLAGS, flags); 467 } 468 469 /* Get ioctl protocol status flags. */ 470 uint32_t 471 libdm_task_get_flags(libdm_task_t libdm_task) 472 { 473 uint32_t flags; 474 475 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 476 DM_IOCTL_FLAGS, &flags); 477 478 return flags; 479 } 480 481 /* Set ioctl protocol status flags. */ 482 uint32_t 483 libdm_task_get_target_num(libdm_task_t libdm_task) 484 { 485 uint32_t count; 486 487 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 488 DM_IOCTL_TARGET_COUNT, &count); 489 490 return count; 491 } 492 493 int32_t 494 libdm_task_get_open_num(libdm_task_t libdm_task) 495 { 496 int32_t count; 497 498 (void)prop_dictionary_get_int32(libdm_task->ldm_task, 499 DM_IOCTL_OPEN, &count); 500 501 return count; 502 } 503 504 uint32_t 505 libdm_task_get_event_num(libdm_task_t libdm_task) 506 { 507 uint32_t event; 508 509 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 510 DM_IOCTL_EVENT, &event); 511 512 return event; 513 } 514 515 /* Set cmd_data dictionary entry to task struct. */ 516 int 517 libdm_task_set_cmd(libdm_cmd_t libdm_cmd, libdm_task_t libdm_task) 518 { 519 520 if ((prop_dictionary_set(libdm_task->ldm_task, 521 DM_IOCTL_CMD_DATA, libdm_cmd->ldm_cmd)) == false) 522 return ENOENT; 523 524 return 0; 525 } 526 527 /* Get cmd_data dictionary entry from task struct */ 528 libdm_cmd_t 529 libdm_task_get_cmd(libdm_task_t libdm_task) 530 { 531 libdm_cmd_t cmd; 532 533 cmd = malloc(sizeof(*cmd)); 534 535 cmd->ldm_cmd = prop_dictionary_get(libdm_task->ldm_task, 536 DM_IOCTL_CMD_DATA); 537 538 if (cmd->ldm_cmd == NULL) { 539 free(cmd); 540 return NULL; 541 } 542 543 /* Get a reference prop_dictionary_get will not get it */ 544 prop_object_retain(cmd->ldm_cmd); 545 546 return cmd; 547 } 548 549 /* Command functions 550 * 551 * Functions for creation, destroing, set, get of command area of 552 * ioctl dictionary. 553 */ 554 libdm_cmd_t 555 libdm_cmd_create(void) 556 { 557 libdm_cmd_t cmd; 558 559 cmd = malloc(sizeof(*cmd)); 560 if (cmd == NULL) 561 return NULL; 562 563 cmd->ldm_cmd = prop_array_create(); 564 565 return cmd; 566 } 567 568 void 569 libdm_cmd_destroy(libdm_cmd_t libdm_cmd) 570 { 571 572 prop_object_release(libdm_cmd->ldm_cmd); 573 free(libdm_cmd); 574 } 575 576 /* Create iterator object for caller this can be used to 577 iterate through all members of cmd array. */ 578 libdm_iter_t 579 libdm_cmd_iter_create(libdm_cmd_t libdm_cmd) 580 { 581 582 libdm_iter_t iter; 583 584 iter = malloc(sizeof(*iter)); 585 if (iter == NULL) 586 return NULL; 587 588 iter->ldm_obji = prop_array_iterator(libdm_cmd->ldm_cmd); 589 590 return iter; 591 } 592 593 int 594 libdm_cmd_set_table(libdm_table_t libdm_table, libdm_cmd_t libdm_cmd) 595 { 596 597 return prop_array_add(libdm_cmd->ldm_cmd, 598 libdm_table->ldm_tbl); 599 } 600 601 602 libdm_target_t 603 libdm_cmd_get_target(libdm_iter_t iter) 604 { 605 libdm_target_t trgt; 606 607 trgt = malloc(sizeof(*trgt)); 608 if (trgt == NULL) 609 return NULL; 610 611 trgt->ldm_trgt = prop_object_iterator_next(iter->ldm_obji); 612 if (trgt->ldm_trgt == NULL) { 613 free(trgt); 614 return NULL; 615 } 616 617 return trgt; 618 } 619 620 libdm_table_t 621 libdm_cmd_get_table(libdm_iter_t iter) 622 { 623 libdm_table_t tbl; 624 625 tbl = malloc(sizeof(*tbl)); 626 if (tbl == NULL) 627 return NULL; 628 629 tbl->ldm_tbl = prop_object_iterator_next(iter->ldm_obji); 630 if (tbl->ldm_tbl == NULL) { 631 free(tbl); 632 return NULL; 633 } 634 635 return tbl; 636 } 637 638 libdm_dev_t 639 libdm_cmd_get_dev(libdm_iter_t iter) 640 { 641 libdm_dev_t dev; 642 643 dev = malloc(sizeof(*dev)); 644 if (dev == NULL) 645 return NULL; 646 647 dev->ldm_dev = prop_object_iterator_next(iter->ldm_obji); 648 if (dev->ldm_dev == NULL) { 649 free(dev); 650 return NULL; 651 } 652 653 return dev; 654 } 655 656 /* 657 * Deps manipulation routines 658 */ 659 uint64_t 660 libdm_cmd_get_deps(libdm_iter_t libdm_iter) 661 { 662 prop_object_t obj; 663 uint64_t deps; 664 665 obj = prop_object_iterator_next(libdm_iter->ldm_obji); 666 deps = prop_number_unsigned_integer_value(obj); 667 668 if (obj != NULL) 669 prop_object_release(obj); 670 671 return deps; 672 } 673 674 /* 675 * Table manipulation routines 676 */ 677 libdm_table_t 678 libdm_table_create(void) 679 { 680 libdm_table_t table; 681 682 table = malloc(sizeof(*table)); 683 if (table == NULL) 684 return NULL; 685 686 table->ldm_tbl = prop_dictionary_create(); 687 688 return table; 689 } 690 691 void 692 libdm_table_destroy(libdm_table_t libdm_table) 693 { 694 695 prop_object_release(libdm_table->ldm_tbl); 696 free(libdm_table); 697 } 698 699 int 700 libdm_table_set_start(uint64_t start, libdm_table_t libdm_table) 701 { 702 703 if (libdm_table == NULL) 704 return ENOENT; 705 706 return prop_dictionary_set_uint64(libdm_table->ldm_tbl, 707 DM_TABLE_START, start); 708 } 709 710 uint64_t 711 libdm_table_get_start(libdm_table_t libdm_table) 712 { 713 uint64_t start; 714 715 if (libdm_table == NULL) 716 return ENOENT; 717 718 (void)prop_dictionary_get_uint64(libdm_table->ldm_tbl, DM_TABLE_START, 719 &start); 720 721 return start; 722 } 723 724 int 725 libdm_table_set_length(uint64_t length, libdm_table_t libdm_table) 726 { 727 728 if (libdm_table == NULL) 729 return ENOENT; 730 731 return prop_dictionary_set_uint64(libdm_table->ldm_tbl, 732 DM_TABLE_LENGTH, length); 733 } 734 735 uint64_t 736 libdm_table_get_length(libdm_table_t libdm_table) 737 { 738 uint64_t length; 739 740 if (libdm_table == NULL) 741 return ENOENT; 742 743 prop_dictionary_get_uint64(libdm_table->ldm_tbl, DM_TABLE_LENGTH, 744 &length); 745 746 return length; 747 } 748 749 int 750 libdm_table_set_target(const char *name, libdm_table_t libdm_table) 751 { 752 753 if (libdm_table == NULL) 754 return ENOENT; 755 756 return prop_dictionary_set_cstring(libdm_table->ldm_tbl, DM_TABLE_TYPE, name); 757 } 758 759 char * 760 libdm_table_get_target(libdm_table_t libdm_table) 761 { 762 char *target; 763 764 if (!prop_dictionary_get_cstring_nocopy(libdm_table->ldm_tbl, DM_TABLE_TYPE, 765 (const char **)&target)) 766 return NULL; 767 768 return target; 769 } 770 771 int 772 libdm_table_set_params(const char *params, libdm_table_t libdm_table) 773 { 774 775 if (libdm_table == NULL) 776 return ENOENT; 777 778 return prop_dictionary_set_cstring(libdm_table->ldm_tbl, 779 DM_TABLE_PARAMS, params); 780 } 781 782 /* 783 * Get table params string from libdm_table_t 784 * returned char * is dynamically allocated caller should free it. 785 */ 786 char * 787 libdm_table_get_params(libdm_table_t libdm_table) 788 { 789 char *params; 790 791 if (!prop_dictionary_get_cstring_nocopy(libdm_table->ldm_tbl, DM_TABLE_PARAMS, 792 (const char **)¶ms)) 793 return NULL; 794 795 return params; 796 } 797 798 int32_t 799 libdm_table_get_status(libdm_table_t libdm_table) 800 { 801 int32_t status; 802 803 (void)prop_dictionary_get_int32(libdm_table->ldm_tbl, DM_TABLE_STAT, 804 &status); 805 806 return status; 807 } 808 809 /* 810 * Target manipulation routines 811 */ 812 void 813 libdm_target_destroy(libdm_target_t libdm_target) 814 { 815 816 prop_object_release(libdm_target->ldm_trgt); 817 free(libdm_target); 818 } 819 820 char * 821 libdm_target_get_name(libdm_target_t libdm_target) 822 { 823 char *name; 824 825 if (!prop_dictionary_get_cstring_nocopy(libdm_target->ldm_trgt, 826 DM_TARGETS_NAME, (const char **)&name)) 827 return NULL; 828 829 return name; 830 } 831 832 int32_t 833 libdm_target_get_version(libdm_target_t libdm_target, uint32_t *ver, size_t size) 834 { 835 prop_array_t prop_ver; 836 size_t i; 837 838 prop_ver = prop_dictionary_get(libdm_target->ldm_trgt, 839 DM_TARGETS_VERSION); 840 841 i = prop_array_count(prop_ver); 842 843 if (i > size) 844 return -i; 845 846 for (i = 0; i < size; i++) 847 prop_array_get_uint32(prop_ver, i, &ver[i]); 848 849 return i; 850 } 851 852 853 /* 854 * Dev manipulation routines 855 */ 856 void 857 libdm_dev_destroy(libdm_dev_t libdm_dev) 858 { 859 860 prop_object_release(libdm_dev->ldm_dev); 861 free(libdm_dev); 862 } 863 864 char * 865 libdm_dev_get_name(libdm_dev_t libdm_dev) 866 { 867 char *name; 868 869 if (!prop_dictionary_get_cstring_nocopy(libdm_dev->ldm_dev, 870 DM_DEV_NAME, (const char **)&name)) 871 return NULL; 872 873 return name; 874 } 875 876 uint32_t 877 libdm_dev_get_minor(libdm_dev_t libdm_dev) 878 { 879 uint32_t dev; 880 881 (void)prop_dictionary_get_uint32(libdm_dev->ldm_dev, DM_DEV_DEV, 882 &dev); 883 884 return dev; 885 } 886 887 int 888 libdm_dev_set_newname(const char *newname, libdm_cmd_t libdm_cmd) 889 { 890 891 if (newname == NULL) 892 return ENOENT; 893 894 return prop_array_set_cstring(libdm_cmd->ldm_cmd, 0, newname); 895 } 896