/*
 * vcreate.c - create vinum objects via the raw VINUM_CREATE ioctl
 * (avoids vinum(8) CLI syntax ambiguity)
 * build: cc -O2 -o vcreate vcreate.c
 * usage: ./vcreate "drive a device /dev/vn0"
 */
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

#define	L	'F'
#define	BUFSIZE	1024
#define	MAX_IOCTL_REPLY 256

#define	VINUM_CREATE	_IOC(IOC_IN | IOC_OUT, L, 64, BUFSIZE)
#define	VINUM_SETSTATE	_IOC(IOC_IN | IOC_OUT, L, 76, MAX_IOCTL_REPLY)

/* mirror of kernel struct vinum_ioctl_msg (vinumio.h:78-91) */
struct vinum_ioctl_msg {
	int index;
	int type;		/* 0 = drive, 1 = sd, 2 = plex, 3 = volume */
	int state;		/* 0 = down, 1 = initializing, 2 = initialized, 3 = up */
	int op;
	int force;
	int recurse;
	int verify;
	int otherobject;
	int rename;
	int64_t offset;
	int blocksize;
};

static int
do_setstate(int fd, int index, int type, int state, int force)
{
	char buf[BUFSIZE];
	struct vinum_ioctl_msg *msg = (struct vinum_ioctl_msg *)buf;

	memset(buf, 0, sizeof(buf));
	msg->index = index;
	msg->type = type;
	msg->state = state;
	msg->force = force;
	if (ioctl(fd, VINUM_SETSTATE, buf) < 0) {
		fprintf(stderr, "setstate(%d,%d,%d): errno %d\n",
		    index, type, state, errno);
		return (-1);
	}
	if (*(int *)buf != 0)
		fprintf(stderr, "setstate(%d,%d,%d): reply %d: %s\n",
		    index, type, state, *(int *)buf, buf + 4);
	else
		printf("setstate %d type %d -> %d ok\n", index, type, state);
	return (0);
}

int
main(int argc, char **argv)
{
	char buf[BUFSIZE];
	int fd, r, i;

	if (argc < 2) {
		fprintf(stderr, "usage: %s 'config line' | -s index type state [force]\n", argv[0]);
		return (2);
	}
	fd = open("/dev/vinum/control", O_RDWR);
	if (fd < 0) {
		perror("/dev/vinum/control");
		return (1);
	}
	if (strcmp(argv[1], "-s") == 0) {
		if (argc < 5)
			return (2);
		do_setstate(fd, atoi(argv[2]), atoi(argv[3]), atoi(argv[4]),
		    (argc > 5) ? atoi(argv[5]) : 0);
		return (0);
	}
	for (i = 1; i < argc; i++) {
		memset(buf, 0, sizeof(buf));
		snprintf(buf, sizeof(buf) - 1, "%s", argv[i]);
		r = ioctl(fd, VINUM_CREATE, buf);
		if (r < 0)
			fprintf(stderr, "ioctl(%s): errno %d\n", argv[i], errno);
		else if (*(int *)buf != 0)
			fprintf(stderr, "create(%s): reply %d: %s\n",
			    argv[i], *(int *)buf, buf + 4);
		else
			printf("created: %s\n", argv[i]);
	}
	return (0);
}
