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_control_close(libdm_control_fd); 169 170 return error; 171 } 172 dict = prop_dictionary_internalize(prefp.pref_plist); 173 #else 174 prop_dictionary_externalize_to_file(libdm_task->ldm_task, "/tmp/libdm_in"); 175 error = prop_dictionary_sendrecv_ioctl(libdm_task->ldm_task, 176 libdm_control_fd, NETBSD_DM_IOCTL, &dict); 177 if ( error != 0) { 178 libdm_control_close(libdm_control_fd); 179 return error; 180 } 181 prop_dictionary_externalize_to_file(dict, "/tmp/libdm_out"); 182 #endif 183 184 libdm_control_close(libdm_control_fd); 185 prop_object_retain(dict); 186 prop_object_release(libdm_task->ldm_task); 187 libdm_task->ldm_task = dict; 188 189 return EXIT_SUCCESS; 190 } 191 192 193 /* Create libdm General task structure */ 194 libdm_task_t 195 libdm_task_create(const char *command) 196 { 197 libdm_task_t task; 198 size_t i,len,slen; 199 prop_array_t ver; 200 201 task = NULL; 202 203 task = malloc(sizeof(*task)); 204 if (task == NULL) 205 return NULL; 206 207 if ((task->ldm_task = prop_dictionary_create()) == NULL) { 208 free(task); 209 return NULL; 210 } 211 212 if ((prop_dictionary_set_cstring(task->ldm_task, DM_IOCTL_COMMAND, 213 command)) == false) { 214 prop_object_release(task->ldm_task); 215 free(task); 216 return NULL; 217 } 218 219 len = strlen(command); 220 221 for (i = 0; cmd_ver[i].cmd != NULL; i++) { 222 slen = strlen(cmd_ver[i].cmd); 223 224 if (len != slen) 225 continue; 226 227 if ((strncmp(command, cmd_ver[i].cmd, slen)) == 0) { 228 ver = prop_array_create(); 229 prop_array_add_uint32(ver, cmd_ver[i].version[0]); 230 prop_array_add_uint32(ver, cmd_ver[i].version[1]); 231 prop_array_add_uint32(ver, cmd_ver[i].version[2]); 232 233 prop_dictionary_set(task->ldm_task, DM_IOCTL_VERSION, 234 ver); 235 236 prop_object_release(ver); 237 break; 238 } 239 } 240 241 return task; 242 } 243 244 void 245 libdm_task_destroy(libdm_task_t libdm_task) 246 { 247 248 if (libdm_task != NULL) 249 prop_object_release(libdm_task->ldm_task); 250 free(libdm_task); 251 } 252 253 /* Set device name */ 254 int 255 libdm_task_set_name(const char *name, libdm_task_t libdm_task) 256 { 257 258 if ((prop_dictionary_set_cstring(libdm_task->ldm_task, 259 DM_IOCTL_NAME, name)) == false) 260 return ENOENT; 261 262 return 0; 263 } 264 265 /* Set device name */ 266 char * 267 libdm_task_get_name(libdm_task_t libdm_task) 268 { 269 char *name; 270 271 if (!prop_dictionary_get_cstring_nocopy(libdm_task->ldm_task, 272 DM_IOCTL_NAME, (const char **)&name)) 273 return NULL; 274 275 return name; 276 } 277 278 /* Set device uuid */ 279 int 280 libdm_task_set_uuid(const char *uuid, libdm_task_t libdm_task) 281 { 282 283 if ((prop_dictionary_set_cstring(libdm_task->ldm_task, 284 DM_IOCTL_UUID, uuid)) == false) 285 return ENOENT; 286 287 return 0; 288 } 289 290 /* Set device name */ 291 char * 292 libdm_task_get_uuid(libdm_task_t libdm_task) 293 { 294 char *uuid; 295 296 if (!prop_dictionary_get_cstring_nocopy(libdm_task->ldm_task, 297 DM_IOCTL_UUID, (const char **)&uuid)) 298 return NULL; 299 300 return uuid; 301 } 302 303 /* Get command name */ 304 char * 305 libdm_task_get_command(libdm_task_t libdm_task) 306 { 307 char *command; 308 309 if (!prop_dictionary_get_cstring_nocopy(libdm_task->ldm_task, 310 DM_IOCTL_COMMAND, (const char **)&command)) 311 return NULL; 312 313 return command; 314 } 315 316 int32_t 317 libdm_task_get_cmd_version(libdm_task_t libdm_task, uint32_t *ver, size_t size) 318 { 319 prop_array_t prop_ver; 320 size_t i; 321 322 prop_ver = prop_dictionary_get(libdm_task->ldm_task, 323 DM_IOCTL_VERSION); 324 325 i = prop_array_count(prop_ver); 326 327 if (i > size) 328 return -i; 329 330 for (i = 0; i < size; i++) 331 prop_array_get_uint32(prop_ver, i, &ver[i]); 332 333 return i; 334 } 335 336 /* Select device minor number. */ 337 int 338 libdm_task_set_minor(uint32_t minor, libdm_task_t libdm_task) 339 { 340 341 if ((prop_dictionary_set_uint32(libdm_task->ldm_task, 342 DM_IOCTL_MINOR, minor)) == false) 343 return ENOENT; 344 345 return 0; 346 } 347 348 /* Select device minor number. */ 349 uint32_t 350 libdm_task_get_minor(libdm_task_t libdm_task) 351 { 352 uint32_t minor; 353 354 minor = 0; 355 356 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 357 DM_IOCTL_MINOR, &minor); 358 359 return minor; 360 } 361 362 /* Set/Del DM_SUSPEND_FLAG for caller. */ 363 void 364 libdm_task_set_suspend_flag(libdm_task_t libdm_task) 365 { 366 uint32_t flags; 367 368 flags = 0; 369 370 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 371 DM_IOCTL_FLAGS, &flags); 372 373 flags |= DM_SUSPEND_FLAG; 374 375 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 376 DM_IOCTL_FLAGS, flags); 377 } 378 379 void 380 libdm_task_del_suspend_flag(libdm_task_t libdm_task) 381 { 382 uint32_t flags; 383 384 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 385 DM_IOCTL_FLAGS, &flags); 386 387 flags &= ~DM_SUSPEND_FLAG; 388 389 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 390 DM_IOCTL_FLAGS, flags); 391 } 392 393 /* Set/Del DM_STATUS_FLAG for caller. */ 394 void 395 libdm_task_set_status_flag(libdm_task_t libdm_task) 396 { 397 uint32_t flags; 398 399 flags = 0; 400 401 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 402 DM_IOCTL_FLAGS, &flags); 403 404 flags |= DM_STATUS_TABLE_FLAG; 405 406 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 407 DM_IOCTL_FLAGS, flags); 408 } 409 410 void 411 libdm_task_del_status_flag(libdm_task_t libdm_task) 412 { 413 uint32_t flags; 414 415 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 416 DM_IOCTL_FLAGS, &flags); 417 418 flags &= ~DM_STATUS_TABLE_FLAG; 419 420 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 421 DM_IOCTL_FLAGS, flags); 422 } 423 424 /* Set/Del DM_EXISTS_FLAG for caller. */ 425 void 426 libdm_task_set_exists_flag(libdm_task_t libdm_task) 427 { 428 uint32_t flags; 429 430 flags = 0; 431 432 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 433 DM_IOCTL_FLAGS, &flags); 434 435 flags |= DM_EXISTS_FLAG; 436 437 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 438 DM_IOCTL_FLAGS, flags); 439 } 440 441 void 442 libdm_task_del_exists_flag(libdm_task_t libdm_task) 443 { 444 uint32_t flags; 445 446 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 447 DM_IOCTL_FLAGS, &flags); 448 449 flags &= ~DM_EXISTS_FLAG; 450 451 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 452 DM_IOCTL_FLAGS, flags); 453 } 454 455 /* Set flags used by LVM this is shortcut and should not be used 456 by anyone else. */ 457 void 458 libdm_task_set_flags(libdm_task_t libdm_task, uint32_t flags) 459 { 460 461 (void)prop_dictionary_set_uint32(libdm_task->ldm_task, 462 DM_IOCTL_FLAGS, flags); 463 } 464 465 /* Get ioctl protocol status flags. */ 466 uint32_t 467 libdm_task_get_flags(libdm_task_t libdm_task) 468 { 469 uint32_t flags; 470 471 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 472 DM_IOCTL_FLAGS, &flags); 473 474 return flags; 475 } 476 477 /* Set ioctl protocol status flags. */ 478 uint32_t 479 libdm_task_get_target_num(libdm_task_t libdm_task) 480 { 481 uint32_t count; 482 483 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 484 DM_IOCTL_TARGET_COUNT, &count); 485 486 return count; 487 } 488 489 int32_t 490 libdm_task_get_open_num(libdm_task_t libdm_task) 491 { 492 int32_t count; 493 494 (void)prop_dictionary_get_int32(libdm_task->ldm_task, 495 DM_IOCTL_OPEN, &count); 496 497 return count; 498 } 499 500 uint32_t 501 libdm_task_get_event_num(libdm_task_t libdm_task) 502 { 503 uint32_t event; 504 505 (void)prop_dictionary_get_uint32(libdm_task->ldm_task, 506 DM_IOCTL_EVENT, &event); 507 508 return event; 509 } 510 511 /* Set cmd_data dictionary entry to task struct. */ 512 int 513 libdm_task_set_cmd(libdm_cmd_t libdm_cmd, libdm_task_t libdm_task) 514 { 515 516 if ((prop_dictionary_set(libdm_task->ldm_task, 517 DM_IOCTL_CMD_DATA, libdm_cmd->ldm_cmd)) == false) 518 return ENOENT; 519 520 return 0; 521 } 522 523 /* Get cmd_data dictionary entry from task struct */ 524 libdm_cmd_t 525 libdm_task_get_cmd(libdm_task_t libdm_task) 526 { 527 libdm_cmd_t cmd; 528 529 cmd = malloc(sizeof(*cmd)); 530 531 cmd->ldm_cmd = prop_dictionary_get(libdm_task->ldm_task, 532 DM_IOCTL_CMD_DATA); 533 534 if (cmd->ldm_cmd == NULL) { 535 free(cmd); 536 return NULL; 537 } 538 539 /* Get a reference prop_dictionary_get will not get it */ 540 prop_object_retain(cmd->ldm_cmd); 541 542 return cmd; 543 } 544 545 /* Command functions 546 * 547 * Functions for creation, destroing, set, get of command area of 548 * ioctl dictionary. 549 */ 550 libdm_cmd_t 551 libdm_cmd_create(void) 552 { 553 libdm_cmd_t cmd; 554 555 cmd = malloc(sizeof(*cmd)); 556 if (cmd == NULL) 557 return NULL; 558 559 cmd->ldm_cmd = prop_array_create(); 560 561 return cmd; 562 } 563 564 void 565 libdm_cmd_destroy(libdm_cmd_t libdm_cmd) 566 { 567 568 prop_object_release(libdm_cmd->ldm_cmd); 569 free(libdm_cmd); 570 } 571 572 /* Create iterator object for caller this can be used to 573 iterate through all members of cmd array. */ 574 libdm_iter_t 575 libdm_cmd_iter_create(libdm_cmd_t libdm_cmd) 576 { 577 578 libdm_iter_t iter; 579 580 iter = malloc(sizeof(*iter)); 581 if (iter == NULL) 582 return NULL; 583 584 iter->ldm_obji = prop_array_iterator(libdm_cmd->ldm_cmd); 585 586 return iter; 587 } 588 589 int 590 libdm_cmd_set_table(libdm_table_t libdm_table, libdm_cmd_t libdm_cmd) 591 { 592 593 return prop_array_add(libdm_cmd->ldm_cmd, 594 libdm_table->ldm_tbl); 595 } 596 597 598 libdm_target_t 599 libdm_cmd_get_target(libdm_iter_t iter) 600 { 601 libdm_target_t trgt; 602 603 trgt = malloc(sizeof(*trgt)); 604 if (trgt == NULL) 605 return NULL; 606 607 trgt->ldm_trgt = prop_object_iterator_next(iter->ldm_obji); 608 if (trgt->ldm_trgt == NULL) { 609 free(trgt); 610 return NULL; 611 } 612 613 return trgt; 614 } 615 616 libdm_table_t 617 libdm_cmd_get_table(libdm_iter_t iter) 618 { 619 libdm_table_t tbl; 620 621 tbl = malloc(sizeof(*tbl)); 622 if (tbl == NULL) 623 return NULL; 624 625 tbl->ldm_tbl = prop_object_iterator_next(iter->ldm_obji); 626 if (tbl->ldm_tbl == NULL) { 627 free(tbl); 628 return NULL; 629 } 630 631 return tbl; 632 } 633 634 libdm_dev_t 635 libdm_cmd_get_dev(libdm_iter_t iter) 636 { 637 libdm_dev_t dev; 638 639 dev = malloc(sizeof(*dev)); 640 if (dev == NULL) 641 return NULL; 642 643 dev->ldm_dev = prop_object_iterator_next(iter->ldm_obji); 644 if (dev->ldm_dev == NULL) { 645 free(dev); 646 return NULL; 647 } 648 649 return dev; 650 } 651 652 /* 653 * Deps manipulation routines 654 */ 655 uint64_t 656 libdm_cmd_get_deps(libdm_iter_t libdm_iter) 657 { 658 prop_object_t obj; 659 uint64_t deps; 660 661 obj = prop_object_iterator_next(libdm_iter->ldm_obji); 662 deps = prop_number_unsigned_integer_value(obj); 663 664 if (obj != NULL) 665 prop_object_release(obj); 666 667 return deps; 668 } 669 670 /* 671 * Table manipulation routines 672 */ 673 libdm_table_t 674 libdm_table_create(void) 675 { 676 libdm_table_t table; 677 678 table = malloc(sizeof(*table)); 679 if (table == NULL) 680 return NULL; 681 682 table->ldm_tbl = prop_dictionary_create(); 683 684 return table; 685 } 686 687 void 688 libdm_table_destroy(libdm_table_t libdm_table) 689 { 690 691 prop_object_release(libdm_table->ldm_tbl); 692 free(libdm_table); 693 } 694 695 int 696 libdm_table_set_start(uint64_t start, libdm_table_t libdm_table) 697 { 698 699 if (libdm_table == NULL) 700 return ENOENT; 701 702 return prop_dictionary_set_uint64(libdm_table->ldm_tbl, 703 DM_TABLE_START, start); 704 } 705 706 uint64_t 707 libdm_table_get_start(libdm_table_t libdm_table) 708 { 709 uint64_t start; 710 711 if (libdm_table == NULL) 712 return ENOENT; 713 714 (void)prop_dictionary_get_uint64(libdm_table->ldm_tbl, DM_TABLE_START, 715 &start); 716 717 return start; 718 } 719 720 int 721 libdm_table_set_length(uint64_t length, libdm_table_t libdm_table) 722 { 723 724 if (libdm_table == NULL) 725 return ENOENT; 726 727 return prop_dictionary_set_uint64(libdm_table->ldm_tbl, 728 DM_TABLE_LENGTH, length); 729 } 730 731 uint64_t 732 libdm_table_get_length(libdm_table_t libdm_table) 733 { 734 uint64_t length; 735 736 if (libdm_table == NULL) 737 return ENOENT; 738 739 prop_dictionary_get_uint64(libdm_table->ldm_tbl, DM_TABLE_LENGTH, 740 &length); 741 742 return length; 743 } 744 745 int 746 libdm_table_set_target(const char *name, libdm_table_t libdm_table) 747 { 748 749 if (libdm_table == NULL) 750 return ENOENT; 751 752 return prop_dictionary_set_cstring(libdm_table->ldm_tbl, DM_TABLE_TYPE, name); 753 } 754 755 char * 756 libdm_table_get_target(libdm_table_t libdm_table) 757 { 758 char *target; 759 760 if (!prop_dictionary_get_cstring_nocopy(libdm_table->ldm_tbl, DM_TABLE_TYPE, 761 (const char **)&target)) 762 return NULL; 763 764 return target; 765 } 766 767 int 768 libdm_table_set_params(const char *params, libdm_table_t libdm_table) 769 { 770 771 if (libdm_table == NULL) 772 return ENOENT; 773 774 return prop_dictionary_set_cstring(libdm_table->ldm_tbl, 775 DM_TABLE_PARAMS, params); 776 } 777 778 /* 779 * Get table params string from libdm_table_t 780 * returned char * is dynamically allocated caller should free it. 781 */ 782 char * 783 libdm_table_get_params(libdm_table_t libdm_table) 784 { 785 char *params; 786 787 if (!prop_dictionary_get_cstring_nocopy(libdm_table->ldm_tbl, DM_TABLE_PARAMS, 788 (const char **)¶ms)) 789 return NULL; 790 791 return params; 792 } 793 794 int32_t 795 libdm_table_get_status(libdm_table_t libdm_table) 796 { 797 int32_t status; 798 799 (void)prop_dictionary_get_int32(libdm_table->ldm_tbl, DM_TABLE_STAT, 800 &status); 801 802 return status; 803 } 804 805 /* 806 * Target manipulation routines 807 */ 808 void 809 libdm_target_destroy(libdm_target_t libdm_target) 810 { 811 812 prop_object_release(libdm_target->ldm_trgt); 813 free(libdm_target); 814 } 815 816 char * 817 libdm_target_get_name(libdm_target_t libdm_target) 818 { 819 char *name; 820 821 if (!prop_dictionary_get_cstring_nocopy(libdm_target->ldm_trgt, 822 DM_TARGETS_NAME, (const char **)&name)) 823 return NULL; 824 825 return name; 826 } 827 828 int32_t 829 libdm_target_get_version(libdm_target_t libdm_target, uint32_t *ver, size_t size) 830 { 831 prop_array_t prop_ver; 832 size_t i; 833 834 prop_ver = prop_dictionary_get(libdm_target->ldm_trgt, 835 DM_TARGETS_VERSION); 836 837 i = prop_array_count(prop_ver); 838 839 if (i > size) 840 return -i; 841 842 for (i = 0; i < size; i++) 843 prop_array_get_uint32(prop_ver, i, &ver[i]); 844 845 return i; 846 } 847 848 849 /* 850 * Dev manipulation routines 851 */ 852 void 853 libdm_dev_destroy(libdm_dev_t libdm_dev) 854 { 855 856 prop_object_release(libdm_dev->ldm_dev); 857 free(libdm_dev); 858 } 859 860 char * 861 libdm_dev_get_name(libdm_dev_t libdm_dev) 862 { 863 char *name; 864 865 if (!prop_dictionary_get_cstring_nocopy(libdm_dev->ldm_dev, 866 DM_DEV_NAME, (const char **)&name)) 867 return NULL; 868 869 return name; 870 } 871 872 uint32_t 873 libdm_dev_get_minor(libdm_dev_t libdm_dev) 874 { 875 uint32_t dev; 876 877 (void)prop_dictionary_get_uint32(libdm_dev->ldm_dev, DM_DEV_DEV, 878 &dev); 879 880 return dev; 881 } 882 883 int 884 libdm_dev_set_newname(const char *newname, libdm_cmd_t libdm_cmd) 885 { 886 887 if (newname == NULL) 888 return ENOENT; 889 890 return prop_array_set_cstring(libdm_cmd->ldm_cmd, 0, newname); 891 } 892