xref: /dflybsd-src/contrib/lvm2/dist/libdm/ioctl/libdm_netbsd.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*      $NetBSD: libdm_netbsd.c,v 1.5 2009/12/05 11:42:24 haad Exp $        */
286d7f5d3SJohn Marino 
386d7f5d3SJohn Marino /*
486d7f5d3SJohn Marino  * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
586d7f5d3SJohn Marino  * All rights reserved.
686d7f5d3SJohn Marino  *
786d7f5d3SJohn Marino  * This code is derived from software contributed to The NetBSD Foundation
886d7f5d3SJohn Marino  * by Adam Hamsik.
986d7f5d3SJohn Marino  *
1086d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
1186d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
1286d7f5d3SJohn Marino  * are met:
1386d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1486d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1586d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1686d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1786d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
1886d7f5d3SJohn Marino  *
1986d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2086d7f5d3SJohn Marino  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2186d7f5d3SJohn Marino  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2286d7f5d3SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2386d7f5d3SJohn Marino  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2486d7f5d3SJohn Marino  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2586d7f5d3SJohn Marino  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2686d7f5d3SJohn Marino  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2786d7f5d3SJohn Marino  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2886d7f5d3SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2986d7f5d3SJohn Marino  * POSSIBILITY OF SUCH DAMAGE.
3086d7f5d3SJohn Marino  */
3186d7f5d3SJohn Marino 
3286d7f5d3SJohn Marino 
3386d7f5d3SJohn Marino #include <sys/ioctl.h>
3486d7f5d3SJohn Marino #include <sys/types.h>
3586d7f5d3SJohn Marino #include <sys/sysctl.h>
3686d7f5d3SJohn Marino 
3786d7f5d3SJohn Marino #include <err.h>
3886d7f5d3SJohn Marino #include <errno.h>
3986d7f5d3SJohn Marino 
4086d7f5d3SJohn Marino #include <stdio.h>
4186d7f5d3SJohn Marino #include <stdlib.h>
4286d7f5d3SJohn Marino #include <unistd.h>
4386d7f5d3SJohn Marino 
4486d7f5d3SJohn Marino #include <dev/dm/netbsd-dm.h>
4586d7f5d3SJohn Marino 
4686d7f5d3SJohn Marino #include <dm-ioctl.h>
4786d7f5d3SJohn Marino 
4886d7f5d3SJohn Marino #include "lib.h"
4986d7f5d3SJohn Marino #include "libdm-netbsd.h"
5086d7f5d3SJohn Marino 
5186d7f5d3SJohn Marino #define DMI_SIZE 16 * 1024
5286d7f5d3SJohn Marino 
5386d7f5d3SJohn Marino static int dm_list_versions(prop_dictionary_t, struct dm_ioctl *);
5486d7f5d3SJohn Marino static int dm_list_devices(prop_dictionary_t, struct dm_ioctl *);
5586d7f5d3SJohn Marino static int dm_dev_deps(prop_dictionary_t, struct dm_ioctl *);
5686d7f5d3SJohn Marino static int dm_table_status(prop_dictionary_t, struct dm_ioctl *);
5786d7f5d3SJohn Marino 
5886d7f5d3SJohn Marino int
nbsd_get_dm_major(uint32_t * major,int type)5986d7f5d3SJohn Marino nbsd_get_dm_major(uint32_t *major,  int type)
6086d7f5d3SJohn Marino {
6186d7f5d3SJohn Marino 	size_t val_len,i;
6286d7f5d3SJohn Marino 	struct kinfo_drivers *kd;
6386d7f5d3SJohn Marino 
6486d7f5d3SJohn Marino 	if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) {
6586d7f5d3SJohn Marino 		printf("sysctlbyname failed");
6686d7f5d3SJohn Marino 		return 0;
6786d7f5d3SJohn Marino 	}
6886d7f5d3SJohn Marino 
6986d7f5d3SJohn Marino 	if ((kd = malloc (val_len)) == NULL){
7086d7f5d3SJohn Marino 		printf("malloc kd info error\n");
7186d7f5d3SJohn Marino 		return 0;
7286d7f5d3SJohn Marino 	}
7386d7f5d3SJohn Marino 
7486d7f5d3SJohn Marino 	if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) {
7586d7f5d3SJohn Marino 		printf("sysctlbyname failed kd");
7686d7f5d3SJohn Marino 		return 0;
7786d7f5d3SJohn Marino 	}
7886d7f5d3SJohn Marino 
7986d7f5d3SJohn Marino 	for (i = 0, val_len /= sizeof(*kd); i < val_len; i++) {
8086d7f5d3SJohn Marino 
8186d7f5d3SJohn Marino 		if (strncmp(kd[i].d_name,DM_NAME,strlen(kd[i].d_name)) == 0){
8286d7f5d3SJohn Marino 
8386d7f5d3SJohn Marino 			if (type == DM_CHAR_MAJOR)
8486d7f5d3SJohn Marino 				/* Set major to dm-driver char major number. */
8586d7f5d3SJohn Marino 				*major = kd[i].d_cmajor;
8686d7f5d3SJohn Marino 			else
8786d7f5d3SJohn Marino 				if (type == DM_BLOCK_MAJOR)
8886d7f5d3SJohn Marino 					*major = kd[i].d_bmajor;
8986d7f5d3SJohn Marino 
9086d7f5d3SJohn Marino 			free(kd);
9186d7f5d3SJohn Marino 
9286d7f5d3SJohn Marino 			return 1;
9386d7f5d3SJohn Marino 		}
9486d7f5d3SJohn Marino 	}
9586d7f5d3SJohn Marino 
9686d7f5d3SJohn Marino 	free(kd);
9786d7f5d3SJohn Marino 
9886d7f5d3SJohn Marino 	return 0;
9986d7f5d3SJohn Marino }
10086d7f5d3SJohn Marino 
10186d7f5d3SJohn Marino int
nbsd_dmi_add_version(const int * version,prop_dictionary_t dm_dict)10286d7f5d3SJohn Marino nbsd_dmi_add_version(const int *version, prop_dictionary_t dm_dict)
10386d7f5d3SJohn Marino {
10486d7f5d3SJohn Marino 	prop_array_t ver;
10586d7f5d3SJohn Marino 	size_t i;
10686d7f5d3SJohn Marino 
10786d7f5d3SJohn Marino 	if ((ver = prop_array_create()) == NULL)
10886d7f5d3SJohn Marino 		return -1;
10986d7f5d3SJohn Marino 
11086d7f5d3SJohn Marino        	for (i=0;i<3;i++)
11186d7f5d3SJohn Marino 		prop_array_set_uint32(ver,i,version[i]);
11286d7f5d3SJohn Marino 
11386d7f5d3SJohn Marino 	if ((prop_dictionary_set(dm_dict,"version",ver)) == false)
11486d7f5d3SJohn Marino 		return -1;
11586d7f5d3SJohn Marino 
11686d7f5d3SJohn Marino 	prop_object_release(ver);
11786d7f5d3SJohn Marino 
11886d7f5d3SJohn Marino 	return 0;
11986d7f5d3SJohn Marino }
12086d7f5d3SJohn Marino 
12186d7f5d3SJohn Marino struct dm_ioctl*
nbsd_dm_dict_to_dmi(prop_dictionary_t dm_dict,const int cmd)12286d7f5d3SJohn Marino nbsd_dm_dict_to_dmi(prop_dictionary_t dm_dict,const int cmd)
12386d7f5d3SJohn Marino {
12486d7f5d3SJohn Marino 	struct dm_ioctl *dmi;
12586d7f5d3SJohn Marino 	prop_array_t ver;
12686d7f5d3SJohn Marino 
12786d7f5d3SJohn Marino 	size_t i;
12886d7f5d3SJohn Marino 	int r;
12986d7f5d3SJohn Marino 	char *name, *uuid;
13086d7f5d3SJohn Marino 	uint32_t major,minor;
13186d7f5d3SJohn Marino 
13286d7f5d3SJohn Marino 	name = NULL;
13386d7f5d3SJohn Marino 	uuid = NULL;
13486d7f5d3SJohn Marino 	minor = 0;
13586d7f5d3SJohn Marino 
13686d7f5d3SJohn Marino 	nbsd_get_dm_major(&major, DM_BLOCK_MAJOR);
13786d7f5d3SJohn Marino 
13886d7f5d3SJohn Marino 	if (!(dmi = dm_malloc(DMI_SIZE)))
13986d7f5d3SJohn Marino 		return NULL;
14086d7f5d3SJohn Marino 
14186d7f5d3SJohn Marino 	memset(dmi,0,DMI_SIZE);
14286d7f5d3SJohn Marino 
14386d7f5d3SJohn Marino 	prop_dictionary_get_int32(dm_dict, DM_IOCTL_OPEN, &dmi->open_count);
14486d7f5d3SJohn Marino 	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_EVENT, &dmi->event_nr);
14586d7f5d3SJohn Marino 	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &dmi->flags);
14686d7f5d3SJohn Marino 	prop_dictionary_get_uint32(dm_dict, DM_IOCTL_TARGET_COUNT,
14786d7f5d3SJohn Marino 		&dmi->target_count);
14886d7f5d3SJohn Marino 
14986d7f5d3SJohn Marino 	if (prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor))
15086d7f5d3SJohn Marino 		dmi->dev = MKDEV(major, minor);
15186d7f5d3SJohn Marino 	else
15286d7f5d3SJohn Marino 		dmi->dev = 0;
15386d7f5d3SJohn Marino 
15486d7f5d3SJohn Marino 	/* Copy name and uuid to dm_ioctl. */
15586d7f5d3SJohn Marino 	if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME,
15686d7f5d3SJohn Marino 		(const char **)&name)){
15786d7f5d3SJohn Marino 		strlcpy(dmi->name, name, DM_NAME_LEN);
15886d7f5d3SJohn Marino 	} else
15986d7f5d3SJohn Marino 		dmi->name[0] = '\0';
16086d7f5d3SJohn Marino 
16186d7f5d3SJohn Marino 	if (prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID,
16286d7f5d3SJohn Marino 		(const char **)&uuid)){
16386d7f5d3SJohn Marino 		strlcpy(dmi->uuid, uuid, DM_UUID_LEN);
16486d7f5d3SJohn Marino 	}  else
16586d7f5d3SJohn Marino 		dmi->uuid[0] = '\0';
16686d7f5d3SJohn Marino 
16786d7f5d3SJohn Marino 	/* dmi parsing values, size of dmi block and offset to data. */
16886d7f5d3SJohn Marino 	dmi->data_size  = DMI_SIZE;
16986d7f5d3SJohn Marino 	dmi->data_start = sizeof(struct dm_ioctl);
17086d7f5d3SJohn Marino 
17186d7f5d3SJohn Marino 	/* Get kernel version from dm_dict. */
17286d7f5d3SJohn Marino 	ver = prop_dictionary_get(dm_dict,DM_IOCTL_VERSION);
17386d7f5d3SJohn Marino 
17486d7f5d3SJohn Marino 	for(i=0; i<3; i++)
17586d7f5d3SJohn Marino 		prop_array_get_uint32(ver,i,&dmi->version[i]);
17686d7f5d3SJohn Marino 
17786d7f5d3SJohn Marino 	switch (cmd){
17886d7f5d3SJohn Marino 
17986d7f5d3SJohn Marino 	case DM_LIST_VERSIONS:
18086d7f5d3SJohn Marino 		r = dm_list_versions(dm_dict,dmi);
18186d7f5d3SJohn Marino 		if (r >= 0)
18286d7f5d3SJohn Marino 			dmi->target_count = r;
18386d7f5d3SJohn Marino 		break;
18486d7f5d3SJohn Marino 
18586d7f5d3SJohn Marino 	case DM_LIST_DEVICES:
18686d7f5d3SJohn Marino 		r = dm_list_devices(dm_dict,dmi);
18786d7f5d3SJohn Marino 		if (r >= 0)
18886d7f5d3SJohn Marino 			dmi->target_count = r;
18986d7f5d3SJohn Marino 		break;
19086d7f5d3SJohn Marino 
19186d7f5d3SJohn Marino 	case DM_TABLE_STATUS:
19286d7f5d3SJohn Marino 		r = dm_table_status(dm_dict,dmi);
19386d7f5d3SJohn Marino 		if (r >= 0)
19486d7f5d3SJohn Marino 			dmi->target_count = r;
19586d7f5d3SJohn Marino 		break;
19686d7f5d3SJohn Marino 
19786d7f5d3SJohn Marino 	case DM_TABLE_DEPS:
19886d7f5d3SJohn Marino 		r = dm_dev_deps(dm_dict,dmi);
19986d7f5d3SJohn Marino 		if (r >= 0)
20086d7f5d3SJohn Marino 			dmi->target_count = r;
20186d7f5d3SJohn Marino 		break;
20286d7f5d3SJohn Marino 	}
20386d7f5d3SJohn Marino 
20486d7f5d3SJohn Marino 	return dmi;
20586d7f5d3SJohn Marino }
20686d7f5d3SJohn Marino 
20786d7f5d3SJohn Marino /*
20886d7f5d3SJohn Marino  * Parse dm_dict when targets command was called and fill dm_ioctl buffer with it.
20986d7f5d3SJohn Marino  *
21086d7f5d3SJohn Marino  * Return number of targets or if failed <0 error.
21186d7f5d3SJohn Marino  */
21286d7f5d3SJohn Marino 
21386d7f5d3SJohn Marino static int
dm_list_versions(prop_dictionary_t dm_dict,struct dm_ioctl * dmi)21486d7f5d3SJohn Marino dm_list_versions(prop_dictionary_t dm_dict, struct dm_ioctl *dmi)
21586d7f5d3SJohn Marino {
21686d7f5d3SJohn Marino 	struct dm_target_versions *dmtv,*odmtv;
21786d7f5d3SJohn Marino 
21886d7f5d3SJohn Marino 	prop_array_t targets,ver;
21986d7f5d3SJohn Marino 	prop_dictionary_t target_dict;
22086d7f5d3SJohn Marino 	prop_object_iterator_t iter;
22186d7f5d3SJohn Marino 
22286d7f5d3SJohn Marino 	char *name;
22386d7f5d3SJohn Marino 	size_t j,i,slen,rec_size;
22486d7f5d3SJohn Marino 
22586d7f5d3SJohn Marino 	odmtv = NULL;
22686d7f5d3SJohn Marino 	name = NULL;
22786d7f5d3SJohn Marino 	j = 0;
22886d7f5d3SJohn Marino 
22986d7f5d3SJohn Marino 	dmtv = (struct dm_target_versions *)((uint8_t *)dmi + dmi->data_start);
23086d7f5d3SJohn Marino 
23186d7f5d3SJohn Marino /*	printf("dmi: vers: %d.%d.%d data_size: %d data_start: %d name: %s t_count: %d\n",
23286d7f5d3SJohn Marino 	    dmi->version[0],dmi->version[1],dmi->version[2],dmi->data_size,dmi->data_start,
23386d7f5d3SJohn Marino 	    dmi->name,dmi->target_count);
23486d7f5d3SJohn Marino 
23586d7f5d3SJohn Marino 	printf("dmi: size: %d -- %p --- %p \n",sizeof(struct dm_ioctl),dmi,dmi+dmi->data_start);
23686d7f5d3SJohn Marino 	printf("dmtv: size: %p --- %p\n",dmtv,(struct dm_target_versions *)(dmi+312));*/
23786d7f5d3SJohn Marino 
23886d7f5d3SJohn Marino 	/* get prop_array of target_version dictionaries */
23986d7f5d3SJohn Marino 	if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){
24086d7f5d3SJohn Marino 
24186d7f5d3SJohn Marino 		iter = prop_array_iterator(targets);
24286d7f5d3SJohn Marino 		if (!iter)
24386d7f5d3SJohn Marino 			err(EXIT_FAILURE,"dm_list_versions %s",__func__);
24486d7f5d3SJohn Marino 
24586d7f5d3SJohn Marino 		while((target_dict = prop_object_iterator_next(iter)) != NULL){
24686d7f5d3SJohn Marino 			j++;
24786d7f5d3SJohn Marino 
24886d7f5d3SJohn Marino 			prop_dictionary_get_cstring_nocopy(target_dict,
24986d7f5d3SJohn Marino 			    DM_TARGETS_NAME,(const char **)&name);
25086d7f5d3SJohn Marino 
25186d7f5d3SJohn Marino 			slen = strlen(name) + 1;
25286d7f5d3SJohn Marino 			rec_size = sizeof(struct dm_target_versions) + slen + 1;
25386d7f5d3SJohn Marino 
25486d7f5d3SJohn Marino 			if (rec_size > dmi->data_size)
25586d7f5d3SJohn Marino 				return -ENOMEM;
25686d7f5d3SJohn Marino 
25786d7f5d3SJohn Marino 			ver = prop_dictionary_get(target_dict,DM_TARGETS_VERSION);
25886d7f5d3SJohn Marino 
25986d7f5d3SJohn Marino 			for (i=0; i<3; i++)
26086d7f5d3SJohn Marino 				prop_array_get_uint32(ver,i,&dmtv->version[i]);
26186d7f5d3SJohn Marino 
26286d7f5d3SJohn Marino 			dmtv->next = rec_size;
26386d7f5d3SJohn Marino 
26486d7f5d3SJohn Marino 			strlcpy(dmtv->name,name,slen);
26586d7f5d3SJohn Marino 
26686d7f5d3SJohn Marino 			odmtv = dmtv;
26786d7f5d3SJohn Marino 
26886d7f5d3SJohn Marino 			dmtv =(struct dm_target_versions *)((uint8_t *)dmtv + rec_size);
26986d7f5d3SJohn Marino 		}
27086d7f5d3SJohn Marino 
27186d7f5d3SJohn Marino 		if (odmtv != NULL)
27286d7f5d3SJohn Marino 			odmtv->next = 0;
27386d7f5d3SJohn Marino 	}
27486d7f5d3SJohn Marino 
27586d7f5d3SJohn Marino 	prop_object_iterator_release(iter);
27686d7f5d3SJohn Marino 	return j;
27786d7f5d3SJohn Marino }
27886d7f5d3SJohn Marino 
27986d7f5d3SJohn Marino /*
28086d7f5d3SJohn Marino  * List all available dm devices in system.
28186d7f5d3SJohn Marino  */
28286d7f5d3SJohn Marino static int
dm_list_devices(prop_dictionary_t dm_dict,struct dm_ioctl * dmi)28386d7f5d3SJohn Marino dm_list_devices(prop_dictionary_t dm_dict, struct dm_ioctl *dmi)
28486d7f5d3SJohn Marino {
28586d7f5d3SJohn Marino 	struct dm_name_list *dml,*odml;
28686d7f5d3SJohn Marino 
28786d7f5d3SJohn Marino 	prop_array_t targets;
28886d7f5d3SJohn Marino 	prop_dictionary_t target_dict;
28986d7f5d3SJohn Marino 	prop_object_iterator_t iter;
29086d7f5d3SJohn Marino 
29186d7f5d3SJohn Marino 	uint32_t minor;
29286d7f5d3SJohn Marino 	uint32_t major;
29386d7f5d3SJohn Marino 
29486d7f5d3SJohn Marino 	char *name;
29586d7f5d3SJohn Marino 	size_t j,slen,rec_size;
29686d7f5d3SJohn Marino 
29786d7f5d3SJohn Marino 	odml = NULL;
29886d7f5d3SJohn Marino 	name = NULL;
29986d7f5d3SJohn Marino 	minor = 0;
30086d7f5d3SJohn Marino 	j = 0;
30186d7f5d3SJohn Marino 
30286d7f5d3SJohn Marino 	nbsd_get_dm_major(&major,DM_BLOCK_MAJOR);
30386d7f5d3SJohn Marino 
30486d7f5d3SJohn Marino 	dml = (struct dm_name_list *)((uint8_t *)dmi + dmi->data_start);
30586d7f5d3SJohn Marino 
30686d7f5d3SJohn Marino 	if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){
30786d7f5d3SJohn Marino 
30886d7f5d3SJohn Marino 		iter = prop_array_iterator(targets);
30986d7f5d3SJohn Marino 		if (!iter)
31086d7f5d3SJohn Marino 			err(EXIT_FAILURE,"dm_list_devices %s",__func__);
31186d7f5d3SJohn Marino 
31286d7f5d3SJohn Marino 		while((target_dict = prop_object_iterator_next(iter)) != NULL){
31386d7f5d3SJohn Marino 
31486d7f5d3SJohn Marino 			prop_dictionary_get_cstring_nocopy(target_dict,
31586d7f5d3SJohn Marino 			    DM_DEV_NAME,(const char **)&name);
31686d7f5d3SJohn Marino 
31786d7f5d3SJohn Marino 			prop_dictionary_get_uint32(target_dict,DM_DEV_DEV,&minor);
31886d7f5d3SJohn Marino 
31986d7f5d3SJohn Marino 			dml->dev = MKDEV(major,minor);
32086d7f5d3SJohn Marino 
32186d7f5d3SJohn Marino 			slen = strlen(name) + 1;
32286d7f5d3SJohn Marino 			rec_size = sizeof(struct dm_name_list) + slen + 1;
32386d7f5d3SJohn Marino 
32486d7f5d3SJohn Marino 			if (rec_size > dmi->data_size)
32586d7f5d3SJohn Marino 				return -ENOMEM;
32686d7f5d3SJohn Marino 
32786d7f5d3SJohn Marino 			dml->next = rec_size;
32886d7f5d3SJohn Marino 
32986d7f5d3SJohn Marino 			strlcpy(dml->name,name,slen);
33086d7f5d3SJohn Marino 
33186d7f5d3SJohn Marino 			odml = dml;
33286d7f5d3SJohn Marino 
33386d7f5d3SJohn Marino 			dml =(struct dm_name_list *)((uint8_t *)dml + rec_size);
33486d7f5d3SJohn Marino 
33586d7f5d3SJohn Marino 			j++;
33686d7f5d3SJohn Marino 		}
33786d7f5d3SJohn Marino 
33886d7f5d3SJohn Marino 		if (odml != NULL)
33986d7f5d3SJohn Marino 			odml->next = 0;
34086d7f5d3SJohn Marino 	}
34186d7f5d3SJohn Marino 	prop_object_iterator_release(iter);
34286d7f5d3SJohn Marino 	return j;
34386d7f5d3SJohn Marino }
34486d7f5d3SJohn Marino 
34586d7f5d3SJohn Marino /*
34686d7f5d3SJohn Marino  * Print status of each table, target arguments, start sector,
34786d7f5d3SJohn Marino  * size and target name.
34886d7f5d3SJohn Marino  */
34986d7f5d3SJohn Marino static int
dm_table_status(prop_dictionary_t dm_dict,struct dm_ioctl * dmi)35086d7f5d3SJohn Marino dm_table_status(prop_dictionary_t dm_dict,struct dm_ioctl *dmi)
35186d7f5d3SJohn Marino {
35286d7f5d3SJohn Marino 	struct dm_target_spec *dmts, *odmts;
35386d7f5d3SJohn Marino 
35486d7f5d3SJohn Marino 	prop_array_t targets;
35586d7f5d3SJohn Marino 	prop_dictionary_t target_dict;
35686d7f5d3SJohn Marino 	prop_object_iterator_t iter;
35786d7f5d3SJohn Marino 
35886d7f5d3SJohn Marino 	char *type,*params,*params_start;
35986d7f5d3SJohn Marino 
36086d7f5d3SJohn Marino 	bool prm;
36186d7f5d3SJohn Marino 	size_t j,plen,rec_size,next;
36286d7f5d3SJohn Marino 
36386d7f5d3SJohn Marino 	j = 0;
36486d7f5d3SJohn Marino 	next = 0;
36586d7f5d3SJohn Marino 	params = NULL;
36686d7f5d3SJohn Marino 	odmts = NULL;
36786d7f5d3SJohn Marino 	rec_size = 0;
36886d7f5d3SJohn Marino 	plen = -1;
36986d7f5d3SJohn Marino 	prm = false;
37086d7f5d3SJohn Marino 
37186d7f5d3SJohn Marino 	dmts = (struct dm_target_spec *)((uint8_t *)dmi + dmi->data_start);
37286d7f5d3SJohn Marino 
37386d7f5d3SJohn Marino 	if ((targets = prop_dictionary_get(dm_dict,DM_IOCTL_CMD_DATA))){
37486d7f5d3SJohn Marino 
37586d7f5d3SJohn Marino 		iter = prop_array_iterator(targets);
37686d7f5d3SJohn Marino 		if (!iter)
37786d7f5d3SJohn Marino 			err(EXIT_FAILURE,"dm_table_status %s",__func__);
37886d7f5d3SJohn Marino 
37986d7f5d3SJohn Marino 		while((target_dict = prop_object_iterator_next(iter)) != NULL){
38086d7f5d3SJohn Marino 
38186d7f5d3SJohn Marino 			prop_dictionary_get_cstring_nocopy(target_dict,
38286d7f5d3SJohn Marino 			    DM_TABLE_TYPE,(const char **)&type);
38386d7f5d3SJohn Marino 
38486d7f5d3SJohn Marino 			prm = prop_dictionary_get_cstring_nocopy(target_dict,
38586d7f5d3SJohn Marino 			    DM_TABLE_PARAMS,(const char **)&params);
38686d7f5d3SJohn Marino 
38786d7f5d3SJohn Marino 			prop_dictionary_get_uint64(target_dict,DM_TABLE_START,&dmts->sector_start);
38886d7f5d3SJohn Marino 			prop_dictionary_get_uint64(target_dict,DM_TABLE_LENGTH,&dmts->length);
38986d7f5d3SJohn Marino 			prop_dictionary_get_int32(target_dict,DM_TABLE_STAT,&dmts->status);
39086d7f5d3SJohn Marino 
39186d7f5d3SJohn Marino 			if (prm)
39286d7f5d3SJohn Marino 				plen = strlen(params) + 1;
39386d7f5d3SJohn Marino 
39486d7f5d3SJohn Marino 			rec_size = sizeof(struct dm_target_spec) + plen;
39586d7f5d3SJohn Marino 
39686d7f5d3SJohn Marino 			/*
39786d7f5d3SJohn Marino 			 * In linux when copying table status from kernel next is
39886d7f5d3SJohn Marino 			 * number of bytes from the start of the first dm_target_spec
39986d7f5d3SJohn Marino 			 * structure. I don't know why but, it has to be done this way.
40086d7f5d3SJohn Marino 			 */
40186d7f5d3SJohn Marino 			next += rec_size;
40286d7f5d3SJohn Marino 
40386d7f5d3SJohn Marino 			if (rec_size > dmi->data_size)
40486d7f5d3SJohn Marino 				return -ENOMEM;
40586d7f5d3SJohn Marino 
40686d7f5d3SJohn Marino 			dmts->next = next;
40786d7f5d3SJohn Marino 
40886d7f5d3SJohn Marino 			strlcpy(dmts->target_type, type, DM_MAX_TYPE_NAME);
40986d7f5d3SJohn Marino 
41086d7f5d3SJohn Marino 			params_start = (char *)dmts + sizeof(struct dm_target_spec);
41186d7f5d3SJohn Marino 
41286d7f5d3SJohn Marino 			if (prm)
41386d7f5d3SJohn Marino 				strlcpy(params_start, params, plen);
41486d7f5d3SJohn Marino 			else
41586d7f5d3SJohn Marino 				params_start = "\0";
41686d7f5d3SJohn Marino 
41786d7f5d3SJohn Marino 
41886d7f5d3SJohn Marino 			odmts = dmts;
41986d7f5d3SJohn Marino 
42086d7f5d3SJohn Marino 			dmts = (struct dm_target_spec *)((uint8_t *)dmts + rec_size);
42186d7f5d3SJohn Marino 
42286d7f5d3SJohn Marino 			j++;
42386d7f5d3SJohn Marino 
42486d7f5d3SJohn Marino 		}
42586d7f5d3SJohn Marino 
42686d7f5d3SJohn Marino 		if (odmts != NULL)
42786d7f5d3SJohn Marino 			odmts->next = 0;
42886d7f5d3SJohn Marino 	}
42986d7f5d3SJohn Marino 	prop_object_iterator_release(iter);
43086d7f5d3SJohn Marino 
43186d7f5d3SJohn Marino 	return j;
43286d7f5d3SJohn Marino }
43386d7f5d3SJohn Marino 
43486d7f5d3SJohn Marino /*
43586d7f5d3SJohn Marino  * Print dm device dependiences, get minor/major number for
43686d7f5d3SJohn Marino  * devices. From kernel I will receive major:minor number of
43786d7f5d3SJohn Marino  * block device used with target. I have to translate it to
43886d7f5d3SJohn Marino  * raw device numbers and use them, because all other parts of lvm2
43986d7f5d3SJohn Marino  * uses raw devices internaly.
44086d7f5d3SJohn Marino  */
44186d7f5d3SJohn Marino static int
dm_dev_deps(prop_dictionary_t dm_dict,struct dm_ioctl * dmi)44286d7f5d3SJohn Marino dm_dev_deps(prop_dictionary_t dm_dict, struct dm_ioctl *dmi)
44386d7f5d3SJohn Marino {
44486d7f5d3SJohn Marino 	struct dm_target_deps *dmtd;
44586d7f5d3SJohn Marino 	struct kinfo_drivers *kd;
44686d7f5d3SJohn Marino 
44786d7f5d3SJohn Marino 	prop_array_t targets;
44886d7f5d3SJohn Marino 	prop_object_iterator_t iter;
44986d7f5d3SJohn Marino 
45086d7f5d3SJohn Marino 	uint32_t major;
45186d7f5d3SJohn Marino 
45286d7f5d3SJohn Marino 	size_t val_len, i, j;
45386d7f5d3SJohn Marino 
45486d7f5d3SJohn Marino 	uint64_t dev_tmp;
45586d7f5d3SJohn Marino 
45686d7f5d3SJohn Marino 	dev_tmp = 0;
45786d7f5d3SJohn Marino 	j = 0;
45886d7f5d3SJohn Marino 	i = 0;
45986d7f5d3SJohn Marino 
46086d7f5d3SJohn Marino 	if (sysctlbyname("kern.drivers",NULL,&val_len,NULL,0) < 0) {
46186d7f5d3SJohn Marino 		printf("sysctlbyname failed");
46286d7f5d3SJohn Marino 		return 0;
46386d7f5d3SJohn Marino 	}
46486d7f5d3SJohn Marino 
46586d7f5d3SJohn Marino 	if ((kd = malloc (val_len)) == NULL){
46686d7f5d3SJohn Marino 		printf("malloc kd info error\n");
46786d7f5d3SJohn Marino 		return 0;
46886d7f5d3SJohn Marino 	}
46986d7f5d3SJohn Marino 
47086d7f5d3SJohn Marino 	if (sysctlbyname("kern.drivers", kd, &val_len, NULL, 0) < 0) {
47186d7f5d3SJohn Marino 		printf("sysctlbyname failed kd");
47286d7f5d3SJohn Marino 		return 0;
47386d7f5d3SJohn Marino 	}
47486d7f5d3SJohn Marino 
47586d7f5d3SJohn Marino 	dmtd = (struct dm_target_deps *)((uint8_t *)dmi + dmi->data_start);
47686d7f5d3SJohn Marino 
47786d7f5d3SJohn Marino 	if ((targets = prop_dictionary_get(dm_dict, DM_IOCTL_CMD_DATA))){
47886d7f5d3SJohn Marino 
47986d7f5d3SJohn Marino 		iter = prop_array_iterator(targets);
48086d7f5d3SJohn Marino 		if (!iter)
48186d7f5d3SJohn Marino 			err(EXIT_FAILURE,"dm_target_deps %s", __func__);
48286d7f5d3SJohn Marino 
48386d7f5d3SJohn Marino 		while((prop_object_iterator_next(iter)) != NULL){
48486d7f5d3SJohn Marino 
48586d7f5d3SJohn Marino 			prop_array_get_uint64(targets, j, &dev_tmp);
48686d7f5d3SJohn Marino 
48786d7f5d3SJohn Marino 			for (i = 0, val_len /= sizeof(*kd); i < val_len; i++){
48886d7f5d3SJohn Marino 				if (kd[i].d_bmajor == MAJOR(dev_tmp)) {
48986d7f5d3SJohn Marino 					major = kd[i].d_cmajor;
49086d7f5d3SJohn Marino 					break;
49186d7f5d3SJohn Marino 				}
49286d7f5d3SJohn Marino 			}
49386d7f5d3SJohn Marino 
49486d7f5d3SJohn Marino 			dmtd->dev[j] = MKDEV(major,MINOR(dev_tmp));
49586d7f5d3SJohn Marino 
49686d7f5d3SJohn Marino 			j++;
49786d7f5d3SJohn Marino 		}
49886d7f5d3SJohn Marino 	}
49986d7f5d3SJohn Marino 
50086d7f5d3SJohn Marino 	dmtd->count = j;
50186d7f5d3SJohn Marino 
50286d7f5d3SJohn Marino 	prop_object_iterator_release(iter);
50386d7f5d3SJohn Marino 
50486d7f5d3SJohn Marino 	return j;
50586d7f5d3SJohn Marino }
506