Module Name:    src
Committed By:   bouyer
Date:           Tue Feb  8 18:09:39 UTC 2011

Added Files:
        src/sbin/dmctl [bouyer-quota2]: Makefile README dmctl.8 dmctl.c

Log Message:
Sync with HEAD


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1.2.2 src/sbin/dmctl/Makefile
cvs rdiff -u -r0 -r1.2.2.2 src/sbin/dmctl/README src/sbin/dmctl/dmctl.8 \
    src/sbin/dmctl/dmctl.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/sbin/dmctl/Makefile
diff -u /dev/null src/sbin/dmctl/Makefile:1.1.2.2
--- /dev/null	Tue Feb  8 18:09:40 2011
+++ src/sbin/dmctl/Makefile	Tue Feb  8 18:09:39 2011
@@ -0,0 +1,24 @@
+PROG=           dmctl
+MAN=		dmctl.8
+WARN= 		4
+SRC=		dmctl.c
+
+BINDIR=		/sbin
+
+#LIBDM_INCLUDE= ${NETBSDSRCDIR}/lib/libdm/
+#LIBDM_OBJDIR= ${NETBSDSRCDIR}/lib/libdm/
+#CFLAGS+= -fno-inline -Wall -O0 -g
+#CPPFLAGS+= -I. -I${LIBDM_INCLUDE}
+
+LDADD+= -ldm
+
+.ifdef RUMP_ACTION
+CPPFLAGS+=  -D RUMP_ACTION
+LDADD+= -lrumpclient
+.endif
+
+LDADD+= -lprop
+
+#LDSTATIC= -static
+
+.include <bsd.prog.mk>

Index: src/sbin/dmctl/README
diff -u /dev/null src/sbin/dmctl/README:1.2.2.2
--- /dev/null	Tue Feb  8 18:09:40 2011
+++ src/sbin/dmctl/README	Tue Feb  8 18:09:39 2011
@@ -0,0 +1,22 @@
+= RUMP howto =
+
+Build rump dm library, build libdm with RUMP_ACTION, build dmct with RUMP_ACTION.
+
+cd lib/libdm/
+RUMP_ACTION=1 USETOOLS=no make
+
+cd ../../sbin/dmctl
+RUMP_ACTION=1 USETOOLS=no make
+RUMP_ACTION=1 USETOOLS=no make -f Makefile.server
+
+== Server Startup ==
+
+RUMP_SP_SERVER=unix:///tmp/dmc
+env RUMP_VERBOSE=1 ./dmctl_server
+
+Server uses /home/haad/test.img file as disk1 device.
+
+== Client Startup ==
+
+RUMP_SP_CLIENT=unix:///tmp/dmc
+./dmctl version
Index: src/sbin/dmctl/dmctl.8
diff -u /dev/null src/sbin/dmctl/dmctl.8:1.2.2.2
--- /dev/null	Tue Feb  8 18:09:40 2011
+++ src/sbin/dmctl/dmctl.8	Tue Feb  8 18:09:39 2011
@@ -0,0 +1,67 @@
+.\"     $NetBSD: dmctl.8,v 1.2.2.2 2011/02/08 18:09:39 bouyer Exp $
+.\"
+.\" Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Adam Hamsik.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.Dd January 23, 2011
+.Dt DMCTL 8
+.Os
+.Sh NAME
+.Nm dmctl
+.Nd manipulate device-mapper driver command
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+.Nm
+works with the device-mapper kernel driver.
+It can send and receive information and commands from the dm driver.
+.Bl -column -offset indent "suspend" "Switch active and passive tables for"
+.Ii Li version Ta Print driver and lib version.
+.It Li targets Ta List available kernel targets.
+.It Li create Ta Create device with [dm device name].
+.It Li ls Ta List existing dm devices.
+.It Li info Ta Get info about device with [dm device name].
+.It Li rename Ta Rename device with [dm device name] to [dm device new name].
+.It Li remove Ta Remove device with [dm device name].
+.It Li resume Ta Resume IO on dm device [dm device name].
+.It Li suspend Ta Suspend IO on dm device [dm device name].
+.It Li deps Ta Print physical dependiences for dm device [dm device name].
+.It Li reload Ta Switch active and passive tables for [dm device name].
+.It Li status Ta Print status for device with [dm device name].
+.It Li table Ta Print active table for device with [dm device name].
+.El
+.Sh SEE ALSO
+.Xr dm 3 ,
+.Xr dm 4
+.Sh HISTORY
+The
+.Nm
+was written and contributed to
+.Nx
+by
+.An Adam Hamsik
+and first appeared in
+.Nx 6.0 .
Index: src/sbin/dmctl/dmctl.c
diff -u /dev/null src/sbin/dmctl/dmctl.c:1.2.2.2
--- /dev/null	Tue Feb  8 18:09:40 2011
+++ src/sbin/dmctl/dmctl.c	Tue Feb  8 18:09:39 2011
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Adam Hamsik.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <prop/proplib.h>
+
+#include <dm.h>
+
+#ifdef RUMP_ACTION
+#include <rump/rump.h>
+#include <rump/rumpclient.h>
+#include <rump/rump_syscalls.h>
+#endif
+
+/* dmctl command is used to communicate with device-mapper driver in NetBSD
+ * it uses libdm library to create and send required data to kernel.
+ *
+ * Main purpose of dmctl is to add posibility to use device-mapper driver
+ * from outside of LVM scope.
+ */
+
+#define DMCTL_CMD_REQ_NODEVNAME 0	/* Command do not require device name */
+#define DMCTL_CMD_REQ_DEVNAME	1	/* Command require device name to work */
+#define DMCTL_CMD_REQ_NEWNAME	2	/* Command require device name and
+					   newname to work */
+struct command {
+	const char *cmd_name;
+	const char *cmd_help;
+	const char *ioctl_cmd_name;
+	int min_args;
+	int (*cmd_func)(int, char *[], libdm_task_t);
+};
+
+int     fd;                             /* file descriptor for device */
+const   char *dvname;                   /* device name */
+const   char *cmdname;                  /* command user issued */
+
+static char * parse_stdin(char *);
+
+static int dmctl_get_version(int, char *[], libdm_task_t);
+static int dmctl_get_targets(int, char *[], libdm_task_t);
+static int dmctl_get_device_info(int, char *[], libdm_task_t);
+static int dmctl_create_dev(int, char *[], libdm_task_t);
+static int dmctl_dev_rename(int, char *[], libdm_task_t);
+static int dmctl_dev_remove(int, char *[], libdm_task_t);
+static int dmctl_dev_resume(int, char *[], libdm_task_t);
+static int dmctl_dev_suspend(int, char *[], libdm_task_t);
+static int dmctl_dev_deps(int, char *[], libdm_task_t);
+static int dmctl_list_devices(int, char *[], libdm_task_t);
+static int dmctl_table_reload(int, char *[], libdm_task_t);
+static int dmctl_table_status(int, char *[], libdm_task_t);
+void usage(void);
+
+struct command commands[] = {
+	{ "version",
+	  "Print driver and lib version.",
+	  NULL, DMCTL_CMD_REQ_NODEVNAME,
+	  dmctl_get_version },
+	{ "targets",
+	  "List available kernel targets.",
+	  NULL, DMCTL_CMD_REQ_NODEVNAME,
+	  dmctl_get_targets },
+	{ "create",
+	  "Create device with [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_create_dev },
+	{ "ls",
+	  "List existing dm devices.",
+	  "names", DMCTL_CMD_REQ_NODEVNAME,
+	  dmctl_list_devices },
+	{ "info",
+	  "Get info about device with [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_get_device_info },
+	{ "rename",
+	  "Rename device with [dm device name] to  [dm device new name].",
+	  NULL, DMCTL_CMD_REQ_NEWNAME,
+	  dmctl_dev_rename },
+	{ "remove",
+	  "Remove device with [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_dev_remove },
+	{ "resume",
+	  "Resume IO on dm device [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_dev_resume },
+	{ "suspend",
+	  "Suspend IO on dm device [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_dev_suspend },
+	{ "deps",
+	  "Print physical dependiences for dm device [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_dev_deps },
+	{ "reload",
+	  "Switch active and passive tables for device with [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_table_reload },
+	{ "status",
+	  "Print status for device with [dm device name].",
+	  "table", DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_table_status },
+	{ "table",
+	  "Print active table for device with [dm device name].",
+	  NULL, DMCTL_CMD_REQ_DEVNAME,
+	  dmctl_table_status },
+	{ NULL,
+	  NULL,
+	  NULL, 0,
+	  NULL },
+};
+
+int
+main(int argc, char *argv[])
+{
+	int i;
+	int oargc;
+	libdm_task_t task;
+
+	oargc = 0;
+
+#ifdef RUMP_ACTION
+	if (rumpclient_init() == -1)
+	  err(EXIT_FAILURE, "rump client init failed");
+#endif
+
+	/* Must have at least: device command */
+	if (argc < 2)
+		usage();
+
+	/* Skip program name, get and skip device name and command. */
+	cmdname = argv[1];
+	if (argc > 2) {
+		oargc = 1;
+		dvname = argv[2];
+	}
+
+	if (argc > 3) {
+		argv += 3;
+		argc -= 3;
+		oargc = 2;
+	} else {
+		argv = 0;
+		argc = 0;
+	}
+
+	for (i = 0; commands[i].cmd_name != NULL; i++)
+		if (strcmp(cmdname, commands[i].cmd_name) == 0)
+			break;
+
+	if (commands[i].cmd_name == NULL)
+		errx(EXIT_FAILURE, "unknown command: %s", cmdname);
+
+	if (commands[i].ioctl_cmd_name != NULL)
+		cmdname = commands[i].ioctl_cmd_name;
+
+	if (oargc != commands[i].min_args) {
+		(void)fprintf(stderr, "Insufficient number of arguments for "
+		    "command: %s specified\n", commands[i].cmd_name);
+		usage();
+	}
+
+	/*
+	 * Create libdm task, and pass it to command handler later.
+	 * Don't release it here because it will be replaced by different
+	 * dictionary received from kernel after libdm_task_run.
+	 */
+	task = libdm_task_create(cmdname);
+
+	(*commands[i].cmd_func)(argc, argv, task);
+
+	return 0;
+}
+
+/*
+ * Print library and kernel driver versions if command can be used only when
+ * major, minor number of library version is <= kernel.
+ */
+static int
+dmctl_get_version(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+	uint32_t ver[3], size;
+
+	size = libdm_task_get_cmd_version(task, ver, sizeof(ver));
+
+	printf("Library protocol version %d:%d:%d\n", ver[0], ver[1], ver[2]);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_get_version: libdm_task_run failed.");
+
+	size = libdm_task_get_cmd_version(task, ver, 3);
+	printf("Kernel protocol version %d:%d:%d\n",ver[0], ver[1], ver[2]);
+
+	libdm_task_destroy(task);
+	return 0;
+}
+
+/*
+ * Get list of available targets from kernel and print them.
+ */
+static int
+dmctl_get_targets(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+	libdm_cmd_t cmd;
+	libdm_iter_t iter;
+	libdm_target_t target;
+	uint32_t ver[3];
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_get_targets: libdm_task_run failed.");
+
+	if ((cmd = libdm_task_get_cmd(task)) == NULL)
+		return ENOENT;
+
+	iter = libdm_cmd_iter_create(cmd);
+
+	while((target = libdm_cmd_get_target(iter)) != NULL){
+		printf("Target name: %s\n", libdm_target_get_name(target));
+
+		libdm_target_get_version(target, ver, sizeof(ver));
+		printf("Target version %d.%d.%d\n\n", ver[0], ver[1], ver[2]);
+
+		libdm_target_destroy(target);
+	}
+
+	libdm_iter_destroy(iter);
+	libdm_cmd_destroy(cmd);
+	libdm_task_destroy(task);
+
+	return 0;
+}
+
+/*
+ * Create device with name used as second parameter.
+ * TODO: Support for UUIDs here.
+ */
+static int
+dmctl_create_dev(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+
+	libdm_task_set_name(dvname, task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_create_dev: libdm_task_run failed.");
+
+	libdm_task_destroy(task);
+	return 0;
+}
+
+/*
+ * Get basic device info from device-mapper driver.
+ */
+static int
+dmctl_get_device_info(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+
+	libdm_task_set_name(dvname, task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_get_device_info: libdm_task_run failed.\n");
+
+	printf("Printing Device info for:\n");
+	printf("Device name: \t\t%s\n", libdm_task_get_name(task));
+	printf("Device uuid: \t\t%s\n", libdm_task_get_uuid(task));
+	printf("Device minor: \t\t%d\n", libdm_task_get_minor(task));
+	printf("Device target number: \t%d\n", libdm_task_get_target_num(task));
+	printf("Device flags: \t\t%d\n", libdm_task_get_flags(task));
+
+	libdm_task_destroy(task);
+	return 0;
+}
+
+/*
+ * List all device in device-mapper driver.
+ */
+static int
+dmctl_list_devices(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+	libdm_cmd_t cmd;
+	libdm_iter_t iter;
+	libdm_dev_t dev;
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_list_devices: libdm_task_run failed.");
+
+	if ((cmd = libdm_task_get_cmd(task)) == NULL)
+		return ENOENT;
+
+	iter = libdm_cmd_iter_create(cmd);
+
+	while((dev = libdm_cmd_get_dev(iter)) != NULL){
+		printf("Device name: %s, device minor: %d \n",
+		    libdm_dev_get_name(dev), libdm_dev_get_minor(dev));
+		libdm_dev_destroy(dev);
+	}
+
+	libdm_iter_destroy(iter);
+	libdm_cmd_destroy(cmd);
+	libdm_task_destroy(task);
+
+	return 0;
+}
+
+/*
+ * Rename device to new name
+ */
+static int
+dmctl_dev_rename(int argc __unused, char *argv[], libdm_task_t task)
+{
+	libdm_cmd_t cmd;
+
+	libdm_task_set_name(dvname, task);
+
+	cmd = libdm_cmd_create();
+	libdm_dev_set_newname(argv[0], cmd);
+	libdm_task_set_cmd(cmd, task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_dev_rename: libdm_task_run failed.");
+
+	libdm_cmd_destroy(cmd);
+	libdm_task_destroy(task);
+
+	return 0;
+}
+
+/*
+ * Remove device from dm device list.
+ */
+static int
+dmctl_dev_remove(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+
+	if (dvname == NULL)
+		return (ENOENT);
+
+	libdm_task_set_name(dvname, task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_dev_remove: libdm_task_run failed.");
+
+	libdm_task_destroy(task);
+	return 0;
+}
+
+/*
+ * Resume device which was suspended or created right now.
+ * Replace table in "active slot" witg table in "inactive slot".
+ */
+static int
+dmctl_dev_resume(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+
+	libdm_task_set_name(dvname, task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_dev_resume: libdm_task_run failed.");
+
+	libdm_task_destroy(task);
+	return 0;
+}
+
+/*
+ * Resume device which was suspended or created right now.
+ * Replace table in "active slot" with table in "inactive slot".
+ */
+static int
+dmctl_dev_suspend(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+
+	libdm_task_set_name(dvname, task);
+	libdm_task_set_suspend_flag(task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_dev_suspend: libdm_task_run failed.");
+
+	libdm_task_destroy(task);
+	return 0;
+}
+
+/*
+ * Get device dependiences from device-mapper. Device dependency is physical
+ * device on which dm device depends.
+ */
+static int
+dmctl_dev_deps(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+	libdm_cmd_t cmd;
+	libdm_iter_t iter;
+	dev_t dev_deps;
+
+	libdm_task_set_name(dvname, task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "dmctl_dev_deps: libdm_task_run failed.");
+
+	if ((cmd = libdm_task_get_cmd(task)) == NULL)
+		return ENOENT;
+
+	iter = libdm_cmd_iter_create(cmd);
+
+	printf("Device %s dependiences \n", dvname);
+
+	while((dev_deps = libdm_cmd_get_deps(iter)) != 0)
+		printf("major: %d minor: %d\n", major(dev_deps), minor(dev_deps));
+
+	libdm_iter_destroy(iter);
+	libdm_cmd_destroy(cmd);
+	libdm_task_destroy(task);
+
+	return 0;
+}
+
+/*
+ * Reload device table to get new one to use.
+ */
+static int
+dmctl_table_reload(int argc, char *argv[], libdm_task_t task)
+{
+	libdm_cmd_t cmd;
+	libdm_table_t table;
+
+	char *params;
+	char *file_path;
+	char target[128];
+	int len;
+	uint64_t start, length;
+
+	file_path = NULL;
+	params = NULL;
+
+	cmd = libdm_cmd_create();
+
+	libdm_task_set_name(dvname, task);
+
+	if (argc != 0)
+		file_path = argv[0];
+
+	while ((params = parse_stdin(file_path)) != NULL) {
+		table = libdm_table_create();
+
+		sscanf(params, "%"PRIu64" %"PRIu64" %s %n", &start, &length, target, &len);
+
+		libdm_table_set_start(start, table);
+		libdm_table_set_length(length, table);
+		libdm_table_set_target(target, table);
+		libdm_table_set_params(params + len, table);
+		libdm_cmd_set_table(table, cmd);
+
+		libdm_table_destroy(table);
+
+		free(params);
+	}
+
+	libdm_task_set_cmd(cmd, task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "libdm_task_run: from dmctl_table_reload failed.");
+
+	libdm_cmd_destroy(cmd);
+	libdm_task_destroy(task);
+	free(params);
+
+	return 0;
+}
+
+/*
+ * Get table status from device.
+ */
+static int
+dmctl_table_status(int argc __unused, char *argv[] __unused, libdm_task_t task)
+{
+	libdm_cmd_t cmd;
+	libdm_table_t table;
+	libdm_iter_t iter;
+
+	libdm_task_set_name(dvname, task);
+	libdm_task_set_status_flag(task);
+
+	if (libdm_task_run(task) != 0)
+		err(EXIT_FAILURE, "libdm_task_run");
+
+	if ((cmd = libdm_task_get_cmd(task)) == NULL)
+		return ENOENT;
+
+	iter = libdm_cmd_iter_create(cmd);
+
+	printf("Getting device table for device %s\n", dvname);
+
+	while ((table = libdm_cmd_get_table(iter)) != NULL) {
+		printf("%10"PRIu64" %10"PRIu64" %s\n",
+			libdm_table_get_start(table),
+			libdm_table_get_length(table),
+			libdm_table_get_target(table));
+		libdm_table_destroy(table);
+	}
+
+	libdm_iter_destroy(iter);
+	libdm_cmd_destroy(cmd);
+	libdm_task_destroy(task);
+
+	return 0;
+}
+
+void
+usage(void)
+{
+	int i;
+
+	(void)fprintf(stderr, "usage: %s command [dm device name]\n"
+	    "Available commands are:\n ", getprogname());
+	for (i = 0; commands[i].cmd_name != NULL; i++)
+		(void)fprintf(stderr, "\t%s\t%s\n", commands[i].cmd_name, commands[i].cmd_help);
+	exit(EXIT_FAILURE);
+}
+
+static char *
+parse_stdin(char *file_path)
+{
+	char *buf, *lbuf;
+	size_t len;
+	FILE *fp;
+
+	lbuf = NULL;
+
+	if (file_path) {
+		if ((fp = fopen(file_path, "r")) == NULL)
+			err(ENOENT, "Cannot open table file\n");
+	} else
+		fp = stdin;
+
+	if ((buf = fgetln(fp, &len)) == NULL)
+		return NULL;
+
+	if (buf[len - 1] != '\n')
+		len++;
+
+	if ((lbuf = malloc(len)) == NULL)
+		err(EXIT_FAILURE, "malloc");
+
+	memcpy(lbuf, buf, len);
+	lbuf[len - 1] = '\0';
+
+	return lbuf;
+}

Reply via email to