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