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 **)¶ms);
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