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 60struct libdm_cmd { 61 prop_array_t ldm_cmd; 62}; 63 64struct libdm_iter { 65 prop_object_iterator_t ldm_obji; 66}; 67 68struct libdm_task { 69 prop_dictionary_t ldm_task; 70}; 71 72struct libdm_table { 73 prop_dictionary_t ldm_tbl; 74}; 75 76struct libdm_target { 77 prop_dictionary_t ldm_trgt; 78}; 79 80struct libdm_dev { 81 prop_dictionary_t ldm_dev; 82}; 83 84struct 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 */ 105static int libdm_control_open(const char *); 106static int libdm_control_close(int); 107 108static int 109libdm_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 122static int 123libdm_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. */ 134void 135libdm_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 */ 146int 147libdm_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 */ 198libdm_task_t 199libdm_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 248void 249libdm_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 */ 258int 259libdm_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 */ 270char * 271libdm_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 */ 283int 284libdm_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 */ 295char * 296libdm_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 */ 308char * 309libdm_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 320int32_t 321libdm_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. */ 341int 342libdm_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. */ 353uint32_t 354libdm_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. */ 367void 368libdm_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 383void 384libdm_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. */ 398void 399libdm_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 414void 415libdm_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. */ 429void 430libdm_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 445void 446libdm_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. */ 461void 462libdm_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. */ 470uint32_t 471libdm_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. */ 482uint32_t 483libdm_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 493int32_t 494libdm_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 504uint32_t 505libdm_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. */ 516int 517libdm_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 */ 528libdm_cmd_t 529libdm_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 */ 554libdm_cmd_t 555libdm_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 568void 569libdm_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. */ 578libdm_iter_t 579libdm_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 593int 594libdm_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 602libdm_target_t 603libdm_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 620libdm_table_t 621libdm_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 638libdm_dev_t 639libdm_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 */ 659uint64_t 660libdm_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 */ 677libdm_table_t 678libdm_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 691void 692libdm_table_destroy(libdm_table_t libdm_table) 693{ 694 695 prop_object_release(libdm_table->ldm_tbl); 696 free(libdm_table); 697} 698 699int 700libdm_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 710uint64_t 711libdm_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 724int 725libdm_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 735uint64_t 736libdm_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 749int 750libdm_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 759char * 760libdm_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 771int 772libdm_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 */ 786char * 787libdm_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 798int32_t 799libdm_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 */ 812void 813libdm_target_destroy(libdm_target_t libdm_target) 814{ 815 816 prop_object_release(libdm_target->ldm_trgt); 817 free(libdm_target); 818} 819 820char * 821libdm_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 832int32_t 833libdm_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 */ 856void 857libdm_dev_destroy(libdm_dev_t libdm_dev) 858{ 859 860 prop_object_release(libdm_dev->ldm_dev); 861 free(libdm_dev); 862} 863 864char * 865libdm_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 876uint32_t 877libdm_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 887int 888libdm_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