示例#1
0
/* Create a drive quick and dirty. */
char *
create_drive(char *device)
{
	struct gv_drive *d;
	struct gctl_req *req;
	const char *errstr;
	char *drivename, *dname;
	int drives, i, flags, volumes, subdisks, plexes;

	flags = plexes = subdisks = volumes = 0;
	drives = 1;
	dname = NULL;

	drivename = find_drive();
	if (drivename == NULL)
		return (NULL);

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "create");
	d = gv_alloc_drive();
	if (d == NULL)
		err(1, "unable to allocate for gv_drive object");

	strlcpy(d->name, drivename, sizeof(d->name));
	copy_device(d, device);
	gctl_ro_param(req, "drive0", sizeof(*d), d);
	gctl_ro_param(req, "flags", sizeof(int), &flags);
	gctl_ro_param(req, "drives", sizeof(int), &drives);
	gctl_ro_param(req, "volumes", sizeof(int), &volumes);
	gctl_ro_param(req, "plexes", sizeof(int), &plexes);
	gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("error creating drive: %s", errstr);
		gctl_free(req);
		return (NULL);
	} else {
		gctl_free(req);
		/* XXX: This is needed because we have to make sure the drives
		 * are created before we return. */
		/* Loop until it's in the config. */
		for (i = 0; i < 100000; i++) {
			dname = find_name("gvinumdrive", GV_TYPE_DRIVE,
			    GV_MAXDRIVENAME);
			/* If we got a different name, quit. */
			if (dname == NULL)
				continue;
			if (strcmp(dname, drivename)) {
				free(dname);
				return (drivename);
			}
			free(dname);
			dname = NULL;
			usleep(100000); /* Sleep for 0.1s */
		}
	}
	gctl_free(req);
	return (drivename);
}
示例#2
0
void
gvinum_resetconfig(void)
{
	struct gctl_req *req;
	const char *errstr;
	char reply[32];

	if (!isatty(STDIN_FILENO)) {
		warn("Please enter this command from a tty device\n");
		return;
	}
	printf(" WARNING!  This command will completely wipe out your gvinum"
	    "configuration.\n"
	    " All data will be lost.  If you really want to do this,"
	    " enter the text\n\n"
	    " NO FUTURE\n"
	    " Enter text -> ");
	fgets(reply, sizeof(reply), stdin);
	if (strcmp(reply, "NO FUTURE\n")) {
		printf("\n No change\n");
		return;
	}
	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "resetconfig");
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("can't reset config: %s", errstr);
		gctl_free(req);
		return;
	}
	gctl_free(req);
	printf("gvinum configuration obliterated\n");
}
示例#3
0
void
gvinum_start(int argc, char **argv)
{
	struct gctl_req *req;
	int i, initsize, j;
	const char *errstr;
	char buf[20];

	/* 'start' with no arguments is a no-op. */
	if (argc == 1)
		return;

	initsize = 0;

	optreset = 1;
	optind = 1;
	while ((j = getopt(argc, argv, "S")) != -1) {
		switch (j) {
		case 'S':
			initsize = atoi(optarg);
			break;
		case '?':
		default:
			return;
		}
	}
	argc -= optind;
	argv += optind;

	if (!initsize)
		initsize = 512;

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "start");
	gctl_ro_param(req, "argc", sizeof(int), &argc);
	gctl_ro_param(req, "initsize", sizeof(int), &initsize);
	if (argc) {
		for (i = 0; i < argc; i++) {
			snprintf(buf, sizeof(buf), "argv%d", i);
			gctl_ro_param(req, buf, -1, argv[i]);
		}
	}
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("can't start: %s", errstr);
		gctl_free(req);
		return;
	}

	gctl_free(req);
}
示例#4
0
文件: gvinum.c 项目: 2asoft/freebsd
static void
gvinum_resetconfig(int argc, char * const *argv)
{
	struct gctl_req *req;
	const char *errstr;
	char reply[32];
	int flags, i;

	flags = 0;
	while ((i = getopt(argc, argv, "f")) != -1) {
		switch (i) {
		case 'f':
			flags |= GV_FLAG_F;
			break;
		default:
			warn("invalid flag: %c", i);
			return;
		}
	}
	if ((flags & GV_FLAG_F) == 0) {
		if (!isatty(STDIN_FILENO)) {
			warn("Please enter this command from a tty device\n");
			return;
		}
		printf(" WARNING!  This command will completely wipe out"
		    " your gvinum configuration.\n"
		    " All data will be lost.  If you really want to do this,"
		    " enter the text\n\n"
		    " NO FUTURE\n"
		    " Enter text -> ");
		fgets(reply, sizeof(reply), stdin);
		if (strcmp(reply, "NO FUTURE\n")) {
			printf("\n No change\n");
			return;
		}
	}
	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "resetconfig");
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("can't reset config: %s", errstr);
		gctl_free(req);
		return;
	}
	gctl_free(req);
	printf("gvinum configuration obliterated\n");
}
示例#5
0
/* 
 * General routine for creating a volume. Mainly for use by concat, mirror,
 * raid5 and stripe commands.
 */
void
create_volume(int argc, char **argv, char *verb)
{
	struct gctl_req *req;
	const char *errstr;
	char buf[BUFSIZ], *drivename, *volname;
	int drives, flags, i;
	off_t stripesize;

	flags = 0;
	drives = 0;
	volname = NULL;
	stripesize = 262144;

	/* XXX: Should we check for argument length? */

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");

	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "-f")) {
			flags |= GV_FLAG_F;
		} else if (!strcmp(argv[i], "-n")) {
			volname = argv[++i];
		} else if (!strcmp(argv[i], "-v")) {
			flags |= GV_FLAG_V;
		} else if (!strcmp(argv[i], "-s")) {
			flags |= GV_FLAG_S;
			if (!strcmp(verb, "raid5"))
				stripesize = gv_sizespec(argv[++i]);
		} else {
			/* Assume it's a drive. */
			snprintf(buf, sizeof(buf), "drive%d", drives++);

			/* First we create the drive. */
			drivename = create_drive(argv[i]); 
			if (drivename == NULL)
				goto bad;
			/* Then we add it to the request. */
			gctl_ro_param(req, buf, -1, drivename);
		}
	}

	gctl_ro_param(req, "stripesize", sizeof(off_t), &stripesize);

	/* Find a free volume name. */
	if (volname == NULL)
		volname = find_name("gvinumvolume", GV_TYPE_VOL, GV_MAXVOLNAME);

	/* Then we send a request to actually create the volumes. */
	gctl_ro_param(req, "verb", -1, verb);
	gctl_ro_param(req, "flags", sizeof(int), &flags); 
	gctl_ro_param(req, "drives", sizeof(int), &drives);
	gctl_ro_param(req, "name", -1, volname);
	errstr = gctl_issue(req);
	if (errstr != NULL)
		warnx("creating %s volume failed: %s", verb, errstr);
bad:
	gctl_free(req);
}
示例#6
0
/*
 * The guts of printconfig.  This is called from gvinum_printconfig and from
 * gvinum_create when called without an argument, in order to give the user
 * something to edit.
 */
void
printconfig(FILE *of, char *comment)
{
	struct gctl_req *req;
	struct utsname uname_s;
	const char *errstr;
	time_t now;
	char buf[GV_CFG_LEN + 1];
	
	uname(&uname_s);
	time(&now);

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "getconfig");
	gctl_ro_param(req, "comment", -1, comment);
	gctl_rw_param(req, "config", sizeof(buf), buf);
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("can't get configuration: %s", errstr);
		return;
	}
	gctl_free(req);

	fprintf(of, "# Vinum configuration of %s, saved at %s",
	    uname_s.nodename,
	    ctime(&now));
	
	if (*comment != '\0')
	    fprintf(of, "# Current configuration:\n");

	fprintf(of, "%s", buf);
}
示例#7
0
void
gvinum_rm(int argc, char **argv)
{
	struct gctl_req *req;
	int flags, i, j;
	const char *errstr;
	char buf[20], *cmd;

	cmd = argv[0];
	flags = 0;
	optreset = 1;
	optind = 1;
	while ((j = getopt(argc, argv, "rf")) != -1) {
		switch (j) {
		case 'f':
			flags |= GV_FLAG_F;
			break;
		case 'r':
			flags |= GV_FLAG_R;
			break;
		case '?':
		default:
			return;
		}
	}
	argc -= optind;
	argv += optind;

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "remove");
	gctl_ro_param(req, "argc", sizeof(int), &argc);
	gctl_ro_param(req, "flags", sizeof(int), &flags);
	if (argc) {
		for (i = 0; i < argc; i++) {
			snprintf(buf, sizeof(buf), "argv%d", i);
			gctl_ro_param(req, buf, -1, argv[i]);
		}
	}
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("can't remove: %s", errstr);
		gctl_free(req);
		return;
	}
	gctl_free(req);
}
示例#8
0
文件: test.c 项目: 2asoft/freebsd
int main(int argc, char *argv[])
{
	struct retval *rv;
	struct gctl_req *req;
	char *param, *value;
	const char *s;
	int c, len;

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "GPT");

	while ((c = getopt(argc, argv, "v")) != -1) {
		switch (c) {
		case 'v':
			verbose = 1;
			break;
		case '?':
		default:
			usage();
			/* NOTREACHED */
			break;
		}
	}

	while (optind < argc) {
		if (!parse(argv[optind++], &param, &value, &len)) {
			if (len > 0) {
				rv = malloc(sizeof(struct retval));
				rv->param = param;
				rv->value = value;
				rv->retval = retval;
				retval = rv;
				gctl_rw_param(req, param, len, value);
			} else
				gctl_ro_param(req, param, -1, value);
		}
	}

	if (verbose)
		gctl_dump(req, stdout);

	s = gctl_issue(req);
	if (s == NULL) {
		printf("PASS");
		while (retval != NULL) {
			rv = retval->retval;
			printf(" %s=%s", retval->param, retval->value);
			free(retval->value);
			free(retval);
			retval = rv;
		}
		printf("\n");
	} else
		printf("FAIL %s\n", s);

	gctl_free(req);
	return (0);
}
示例#9
0
void
gvinum_setstate(int argc, char **argv)
{
	struct gctl_req *req;
	int flags, i;
	const char *errstr;

	flags = 0;

	optreset = 1;
	optind = 1;

	while ((i = getopt(argc, argv, "f")) != -1) {
		switch (i) {
		case 'f':
			flags |= GV_FLAG_F;
			break;
		case '?':
		default:
			warn("invalid flag: %c", i);
			return;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc != 2) {
		warnx("usage: setstate [-f] <state> <obj>");
		return;
	}

	/*
	 * XXX: This hack is needed to avoid tripping over (now) invalid
	 * 'classic' vinum states and will go away later.
	 */
	if (strcmp(argv[0], "up") && strcmp(argv[0], "down") &&
	    strcmp(argv[0], "stale")) {
		warnx("invalid state '%s'", argv[0]);
		return;
	}

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "setstate");
	gctl_ro_param(req, "state", -1, argv[0]);
	gctl_ro_param(req, "object", -1, argv[1]);
	gctl_ro_param(req, "flags", sizeof(int), &flags);

	errstr = gctl_issue(req);
	if (errstr != NULL)
		warnx("%s", errstr);
	gctl_free(req);
}
示例#10
0
void
gvinum_parityop(int argc, char **argv, int rebuild)
{
	struct gctl_req *req;
	int flags, i;
	const char *errstr;
	char *op, *msg;

	if (rebuild) {
		op = "rebuildparity";
		msg = "Rebuilding";
	} else {
		op = "checkparity";
		msg = "Checking";
	}

	optreset = 1;
	optind = 1;
	flags = 0;
	while ((i = getopt(argc, argv, "fv")) != -1) {
		switch (i) {
		case 'f':
			flags |= GV_FLAG_F;
			break;
		case 'v':
			flags |= GV_FLAG_V;
			break;
		case '?':
		default:
			warnx("invalid flag '%c'", i);
			return;
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 1) {
		warn("usage: %s [-f] [-v] <plex>", op);
		return;
	}

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, op);
	gctl_ro_param(req, "rebuild", sizeof(int), &rebuild);
	gctl_ro_param(req, "flags", sizeof(int), &flags);
	gctl_ro_param(req, "plex", -1, argv[0]);

	errstr = gctl_issue(req);
	if (errstr)
		warnx("%s\n", errstr);
	gctl_free(req);
}
示例#11
0
/* Note that move is currently of form '[-r] target object [...]' */
void
gvinum_move(int argc, char **argv)
{
	struct gctl_req *req;
	const char *errstr;
	char buf[20];
	int flags, i, j;

	flags = 0;
	if (argc) {
		optreset = 1;
		optind = 1;
		while ((j = getopt(argc, argv, "f")) != -1) {
			switch (j) {
			case 'f':
				flags |= GV_FLAG_F;
				break;
			case '?':
			default:
				return;
			}
		}
		argc -= optind;
		argv += optind;
	}

	switch (argc) {
		case 0:
			warnx("no destination or object(s) to move specified");
			return;
		case 1:
			warnx("no object(s) to move specified");
			return;
		default:
			break;
	}

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "move");
	gctl_ro_param(req, "argc", sizeof(int), &argc);
	gctl_ro_param(req, "flags", sizeof(int), &flags);
	gctl_ro_param(req, "destination", -1, argv[0]);
	for (i = 1; i < argc; i++) {
		snprintf(buf, sizeof(buf), "argv%d", i);
		gctl_ro_param(req, buf, -1, argv[i]);
	}
	errstr = gctl_issue(req);
	if (errstr != NULL)
		warnx("can't move object(s):  %s", errstr);
	gctl_free(req);
	return;
}
示例#12
0
void
gvinum_rename(int argc, char **argv)
{
	struct gctl_req *req;
	const char *errstr;
	int flags, j;

	flags = 0;

	if (argc) {
		optreset = 1;
		optind = 1;
		while ((j = getopt(argc, argv, "r")) != -1) {
			switch (j) {
			case 'r':
				flags |= GV_FLAG_R;
				break;
			case '?':
			default:
				return;
			}
		}
		argc -= optind;
		argv += optind;
	}

	switch (argc) {
		case 0:
			warnx("no object to rename specified");
			return;
		case 1:
			warnx("no new name specified");
			return;
		case 2:
			break;
		default:
			warnx("more than one new name specified");
			return;
	}

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "rename");
	gctl_ro_param(req, "flags", sizeof(int), &flags);
	gctl_ro_param(req, "object", -1, argv[0]);
	gctl_ro_param(req, "newname", -1, argv[1]);
	errstr = gctl_issue(req);
	if (errstr != NULL)
		warnx("can't rename object:  %s", errstr);
	gctl_free(req);
	return;
}
示例#13
0
void
gvinum_saveconfig(void)
{
	struct gctl_req *req;
	const char *errstr;

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "saveconfig");
	errstr = gctl_issue(req);
	if (errstr != NULL)
		warnx("can't save configuration: %s", errstr);
	gctl_free(req);
}
示例#14
0
static int
write_boot(const char *disk, u_char *boot)
{
	int fd, n, i;
	char buf[MAXPATHLEN];
	const char *q;
	struct gctl_req *grq;

	fd = open(disk, O_WRONLY, 0666);
	if (fd != -1) {
		if ((n = write(fd, boot, BOOTSIZE)) < 0)
			err(1, "%s", disk);
		if (n != BOOTSIZE)
			errx(1, "%s: short write", disk);
		close(fd);
		return 0;
	}

	grq = gctl_get_handle();
	gctl_ro_param(grq, "verb", -1, "write PC98");
	gctl_ro_param(grq, "class", -1, "PC98");
	q = strrchr(disk, '/');
	if (q == NULL)
		q = disk;
	else
		q++;
	gctl_ro_param(grq, "geom", -1, q);
	gctl_ro_param(grq, "data", BOOTSIZE, boot);
	q = gctl_issue(grq);
	if (q == NULL)
		return 0;

	warnx("%s: %s", disk, q);
	gctl_free(grq);

	for (i = 0; i < PC98_NPARTS; i++) {
		snprintf(buf, sizeof(buf), "%ss%d", disk, i + 1);
		fd = open(buf, O_RDONLY);
		if (fd < 0)
			continue;
		n = ioctl(fd, DIOCSPC98, boot);
		if (n != 0)
			err(1, "%s: ioctl DIOCSPC98", disk);
		close(fd);
		return 0;
	}

	err(1, "%s", disk);
}
示例#15
0
/* Detach a plex or subdisk from its parent. */
void
gvinum_detach(int argc, char **argv)
{
	const char *errstr;
	struct gctl_req *req;
	int flags, i;

	flags = 0;
	optreset = 1;
	optind = 1;
	while ((i = getopt(argc, argv, "f")) != -1) {
		switch(i) {
		case 'f':
			flags |= GV_FLAG_F;
			break;
		default:
			warn("invalid flag: %c", i);
			return;
		}
	}
	argc -= optind;
	argv += optind;
	if (argc != 1) {
		warnx("usage: detach [-f] <subdisk> | <plex>");
		return;
	}

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "detach");
	gctl_ro_param(req, "object", -1, argv[0]);
	gctl_ro_param(req, "flags", sizeof(int), &flags);

	errstr = gctl_issue(req);
	if (errstr != NULL)
		warnx("detach failed: %s", errstr);
	gctl_free(req);
}
示例#16
0
/* Attach a plex to a volume or a subdisk to a plex. */
void
gvinum_attach(int argc, char **argv)
{
	struct gctl_req *req;
	const char *errstr;
	int rename;
	off_t offset;

	rename = 0;
	offset = -1;
	if (argc < 3) {
		warnx("usage:\tattach <subdisk> <plex> [rename] "
		    "[<plexoffset>]\n"
		    "\tattach <plex> <volume> [rename]");
		return;
	}
	if (argc > 3) {
		if (!strcmp(argv[3], "rename")) {
			rename = 1;
			if (argc == 5)
				offset = strtol(argv[4], NULL, 0);
		} else
			offset = strtol(argv[3], NULL, 0);
	}
	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "attach");
	gctl_ro_param(req, "child", -1, argv[1]);
	gctl_ro_param(req, "parent", -1, argv[2]);
	gctl_ro_param(req, "offset", sizeof(off_t), &offset);
	gctl_ro_param(req, "rename", sizeof(int), &rename);
	errstr = gctl_issue(req);
	if (errstr != NULL)
		warnx("attach failed: %s", errstr);
	gctl_free(req);
}
示例#17
0
/*
 * Write out the mbr to the specified file.
 */
static void
write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size)
{
	struct gctl_req *grq;
	const char *errmsg;
	char *pname;
	ssize_t n;
	int fd;

	fd = open(fname, O_WRONLY | flags, 0666);
	if (fd != -1) {
		n = write(fd, mbr, mbr_size);
		close(fd);
		if (n != mbr_size)
			errx(1, "%s: short write", fname);
		return;
	}

	/*
	 * If we're called to write to a backup file, don't try to
	 * write through GEOM.
	 */
	if (flags != 0)
		err(1, "can't open file %s to write backup", fname);

	/* Try open it read only. */
	fd = open(fname, O_RDONLY);
	if (fd == -1) {
		warn("error opening %s", fname);
		return;
	}

	pname = g_providername(fd);
	if (pname == NULL) {
		warn("error getting providername for %s", fname);
		return;
	}

	/* First check that GEOM_PART is available */
	if (geom_class_available("PART") != 0) {
		grq = gctl_get_handle();
		gctl_ro_param(grq, "class", -1, "PART");
		gctl_ro_param(grq, "arg0", -1, pname);
		gctl_ro_param(grq, "verb", -1, "bootcode");
		gctl_ro_param(grq, "bootcode", mbr_size, mbr);
		gctl_ro_param(grq, "flags", -1, "C");
		errmsg = gctl_issue(grq);
		if (errmsg != NULL && errmsg[0] != '\0')
			errx(1, "GEOM_PART: write bootcode to %s failed: %s",
			    fname, errmsg);
		gctl_free(grq);
	} else if (geom_class_available("MBR") != 0) {
		grq = gctl_get_handle();
		gctl_ro_param(grq, "verb", -1, "write MBR");
		gctl_ro_param(grq, "class", -1, "MBR");
		gctl_ro_param(grq, "geom", -1, pname);
		gctl_ro_param(grq, "data", mbr_size, mbr);
		errmsg = gctl_issue(grq);
		if (errmsg != NULL)
			err(1, "GEOM_MBR: write MBR to %s failed", fname);
		gctl_free(grq);
	} else
		errx(1, "can't write MBR to %s", fname);
	free(pname);
}
示例#18
0
void
gvinum_list(int argc, char **argv)
{
	struct gctl_req *req;
	int flags, i, j;
	const char *errstr;
	char buf[20], *cmd, config[GV_CFG_LEN + 1];

	flags = 0;
	cmd = "list";

	if (argc) {
		optreset = 1;
		optind = 1;
		cmd = argv[0];
		while ((j = getopt(argc, argv, "rsvV")) != -1) {
			switch (j) {
			case 'r':
				flags |= GV_FLAG_R;
				break;
			case 's':
				flags |= GV_FLAG_S;
				break;
			case 'v':
				flags |= GV_FLAG_V;
				break;
			case 'V':
				flags |= GV_FLAG_V;
				flags |= GV_FLAG_VV;
				break;
			case '?':
			default:
				return;
			}
		}
		argc -= optind;
		argv += optind;

	}

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "list");
	gctl_ro_param(req, "cmd", -1, cmd);
	gctl_ro_param(req, "argc", sizeof(int), &argc);
	gctl_ro_param(req, "flags", sizeof(int), &flags);
	gctl_rw_param(req, "config", sizeof(config), config);
	if (argc) {
		for (i = 0; i < argc; i++) {
			snprintf(buf, sizeof(buf), "argv%d", i);
			gctl_ro_param(req, buf, -1, argv[i]);
		}
	}
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("can't get configuration: %s", errstr);
		gctl_free(req);
		return;
	}

	printf("%s", config);
	gctl_free(req);
	return;
}
示例#19
0
/* Find a free name for an object given a a prefix. */
char *
find_name(const char *prefix, int type, int namelen)
{
	struct gctl_req *req;
	char comment[1], buf[GV_CFG_LEN - 1], *name, *sname, *ptr;
	const char *errstr;
	int i, n, begin, len, conflict;
	char line[1024];

	comment[0] = '\0';

	/* Find a name. Fetch out configuration first. */
	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "getconfig");
	gctl_ro_param(req, "comment", -1, comment);
	gctl_rw_param(req, "config", sizeof(buf), buf);
	errstr = gctl_issue(req);
	if (errstr != NULL) {
		warnx("can't get configuration: %s", errstr);
		return (NULL);
	}
	gctl_free(req);

	begin = 0;
	len = strlen(buf);
	i = 0;
	sname = malloc(namelen + 1);

	/* XXX: Max object setting? */
	for (n = 0; n < 10000; n++) {
		snprintf(sname, namelen, "%s%d", prefix, n);
		conflict = 0;
		begin = 0;
		/* Loop through the configuration line by line. */
		for (i = 0; i < len; i++) {
			if (buf[i] == '\n' || buf[i] == '\0') {
				ptr = buf + begin;
				strlcpy(line, ptr, (i - begin) + 1);
				begin = i + 1;
				switch (type) {
				case GV_TYPE_DRIVE:
					name = find_pattern(line, "drive");
					break;
				case GV_TYPE_VOL:
					name = find_pattern(line, "volume");
					break;
				case GV_TYPE_PLEX:
				case GV_TYPE_SD:
					name = find_pattern(line, "name");
					break;
				default:
					printf("Invalid type given\n");
					continue;
				}
				if (name == NULL)
					continue;
				if (!strcmp(sname, name)) {
					conflict = 1;
					/* XXX: Could quit the loop earlier. */
				}
			}
		}
		if (!conflict)
			return (sname);
	}
	free(sname);
	return (NULL);
}
示例#20
0
static void
write_label(struct sun_disklabel *sl, const char *disk, const char *bootpath)
{
	char path[MAXPATHLEN];
	char boot[SUN_BOOTSIZE];
	char buf[SUN_SIZE];
	const char *errstr;
	off_t off;
	int bfd;
	int fd;
	int i;
	struct gctl_req *grq;

	sl->sl_magic = SUN_DKMAGIC;

	if (check_label(sl) != 0)
		errx(1, "invalid label");

	bzero(buf, sizeof(buf));
	sunlabel_enc(buf, sl);

	if (nflag) {
		print_label(sl, disk, stdout);
		return;
	}
	if (Bflag) {
		if ((bfd = open(bootpath, O_RDONLY)) < 0)
			err(1, "open %s", bootpath);
		i = read(bfd, boot, sizeof(boot));
		if (i < 0)
			err(1, "read");
		else if (i != sizeof (boot))
			errx(1, "read wrong size boot code (%d)", i);
		close(bfd);
	}
	snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk);
	fd = open(path, O_RDWR);
	if (fd < 0) {
		grq = gctl_get_handle();
		gctl_ro_param(grq, "verb", -1, "write label");
		gctl_ro_param(grq, "class", -1, "SUN");
		gctl_ro_param(grq, "geom", -1, disk);
		gctl_ro_param(grq, "label", sizeof buf, buf);
		errstr = gctl_issue(grq);
		if (errstr != NULL)
			errx(1, "%s", errstr);
		gctl_free(grq);
		if (Bflag) {
			grq = gctl_get_handle();
			gctl_ro_param(grq, "verb", -1, "write bootcode");
			gctl_ro_param(grq, "class", -1, "SUN");
			gctl_ro_param(grq, "geom", -1, disk);
			gctl_ro_param(grq, "bootcode", sizeof boot, boot);
			errstr = gctl_issue(grq);
			if (errstr != NULL)
				errx(1, "%s", errstr);
			gctl_free(grq);
		}
	} else {
		if (lseek(fd, 0, SEEK_SET) < 0)
			err(1, "lseek");
		if (write(fd, buf, sizeof(buf)) != sizeof(buf))
			err (1, "write");
		if (Bflag) {
			for (i = 0; i < SUN_NPART; i++) {
				if (sl->sl_part[i].sdkp_nsectors == 0)
					continue;
				off = sl->sl_part[i].sdkp_cyloffset *
				    sl->sl_ntracks * sl->sl_nsectors * 512;
				/*
				 * Ignore first SUN_SIZE bytes of boot code to
				 * avoid overwriting the label.
				 */
				if (lseek(fd, off + SUN_SIZE, SEEK_SET) < 0)
					err(1, "lseek");
				if (write(fd, boot + SUN_SIZE,
				    sizeof(boot) - SUN_SIZE) !=
				    sizeof(boot) - SUN_SIZE)
					err(1, "write");
			}
		}
		close(fd);
	}
	exit(0);
}
示例#21
0
static int
do_single(int argc, char **argv, int action)
{
	char *cp, *cp2;
	int ccd, noflags = 0, i, ileave, flags = 0;
	struct gctl_req *grq;
	char const *errstr;
	char buf1[BUFSIZ];
	int ex;

	/*
	 * If unconfiguring, all arguments are treated as ccds.
	 */
	if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) {
		ex = 0;
		for (; argc != 0;) {
			cp = *argv++; --argc;
			if ((ccd = resolve_ccdname(cp)) < 0) {
				warnx("invalid ccd name: %s", cp);
				continue;
			}
			grq = gctl_get_handle();
			gctl_ro_param(grq, "verb", -1, "destroy geom");
			gctl_ro_param(grq, "class", -1, "CCD");
			sprintf(buf1, "ccd%d", ccd);
			gctl_ro_param(grq, "geom", -1, buf1);
			errstr = gctl_issue(grq);
			if (errstr == NULL) {		
				if (verbose)
					printf("%s unconfigured\n", cp);
				gctl_free(grq);
				continue;
			}
			warnx(
			    "%s\nor possibly kernel and ccdconfig out of sync",
			    errstr);
			ex = 1;
		}
		return (ex);
	}

	/* Make sure there are enough arguments. */
	if (argc < 4) {
		if (argc == 3) {
			/* Assume that no flags are specified. */
			noflags = 1;
		} else {
			if (action == CCD_CONFIGALL) {
				warnx("%s: bad line: %d", ccdconf, lineno);
				return (1);
			} else
				usage();
		}
	}

	/* First argument is the ccd to configure. */
	cp = *argv++; --argc;
	if ((ccd = resolve_ccdname(cp)) < 0) {
		warnx("invalid ccd name: %s", cp);
		return (1);
	}

	/* Next argument is the interleave factor. */
	cp = *argv++; --argc;
	errno = 0;	/* to check for ERANGE */
	ileave = (int)strtol(cp, &cp2, 10);
	if ((errno == ERANGE) || (ileave < 0) || (*cp2 != '\0')) {
		warnx("invalid interleave factor: %s", cp);
		return (1);
	}

	if (noflags == 0) {
		/* Next argument is the ccd configuration flags. */
		cp = *argv++; --argc;
		if ((flags = flags_to_val(cp)) < 0) {
			warnx("invalid flags argument: %s", cp);
			return (1);
		}
	}
	grq = gctl_get_handle();
	gctl_ro_param(grq, "verb", -1, "create geom");
	gctl_ro_param(grq, "class", -1, "CCD");
	gctl_ro_param(grq, "unit", sizeof(ccd), &ccd);
	gctl_ro_param(grq, "ileave", sizeof(ileave), &ileave);
	if (flags & CCDF_UNIFORM)
		gctl_ro_param(grq, "uniform", -1, "");
	if (flags & CCDF_MIRROR)
		gctl_ro_param(grq, "mirror", -1, "");
	if (flags & CCDF_NO_OFFSET)
		gctl_ro_param(grq, "no_offset", -1, "");
	if (flags & CCDF_LINUX)
		gctl_ro_param(grq, "linux", -1, "");
	gctl_ro_param(grq, "nprovider", sizeof(argc), &argc);
	for (i = 0; i < argc; i++) {
		sprintf(buf1, "provider%d", i);
		cp = argv[i];
		if (!strncmp(cp, _PATH_DEV, strlen(_PATH_DEV)))
			cp += strlen(_PATH_DEV);
		gctl_ro_param(grq, buf1, -1, cp);
	}
	gctl_rw_param(grq, "output", sizeof(buf1), buf1);
	errstr = gctl_issue(grq);
	if (errstr == NULL) {		
		if (verbose) {
			printf("%s", buf1);
		}
		gctl_free(grq);
		return (0);
	}
	warnx(
	    "%s\nor possibly kernel and ccdconfig out of sync",
	    errstr);
	return (1);
}
示例#22
0
/* Grow a subdisk by adding disk backed by provider. */
void
gvinum_grow(int argc, char **argv)
{
	struct gctl_req *req;
	char *drive, *sdname;
	char sdprefix[GV_MAXSDNAME];
	struct gv_drive *d;
	struct gv_sd *s;
	const char *errstr;
	int drives, volumes, plexes, subdisks, flags;

	drives = volumes = plexes = subdisks = 0;
	if (argc < 3) {
		warnx("usage:\tgrow plex drive\n");
		return;
	}

	s = gv_alloc_sd();
	if (s == NULL) {
		warn("unable to create subdisk");
		return;
	}
	d = gv_alloc_drive();
	if (d == NULL) {
		warn("unable to create drive");
		free(s);
		return;
	}
	/* Lookup device and set an appropriate drive name. */
	drive = find_drive();
	if (drive == NULL) {
		warn("unable to find an appropriate drive name");
		free(s);
		free(d);
		return;
	}
	strlcpy(d->name, drive, sizeof(d->name));
	copy_device(d, argv[2]);

	drives = 1;

	/* We try to use the plex name as basis for the subdisk name. */
	snprintf(sdprefix, sizeof(sdprefix), "%s.s", argv[1]);
	sdname = find_name(sdprefix, GV_TYPE_SD, GV_MAXSDNAME);
	if (sdname == NULL) {
		warn("unable to find an appropriate subdisk name");
		free(s);
		free(d);
		free(drive);
		return;
	}
	strlcpy(s->name, sdname, sizeof(s->name));
	free(sdname);
	strlcpy(s->plex, argv[1], sizeof(s->plex));
	strlcpy(s->drive, d->name, sizeof(s->drive));
	subdisks = 1;

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "create");
	gctl_ro_param(req, "flags", sizeof(int), &flags);
	gctl_ro_param(req, "volumes", sizeof(int), &volumes);
	gctl_ro_param(req, "plexes", sizeof(int), &plexes);
	gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
	gctl_ro_param(req, "drives", sizeof(int), &drives);
	gctl_ro_param(req, "drive0", sizeof(*d), d);
	gctl_ro_param(req, "sd0", sizeof(*s), s);
	errstr = gctl_issue(req);
	free(drive);
	if (errstr != NULL) {
		warnx("unable to grow plex: %s", errstr);
		free(s);
		free(d);
		return;
	}
	gctl_free(req);
}
示例#23
0
static int
writelabel(void)
{
	int i, fd, serrno;
	struct gctl_req *grq;
	char const *errstr;
	struct disklabel *lp = &lab;

	if (disable_write) {
		warnx("write to disk label suppressed - label was as follows:");
		display(stdout, NULL);
		return (0);
	}

	lp->d_magic = DISKMAGIC;
	lp->d_magic2 = DISKMAGIC;
	lp->d_checksum = 0;
	lp->d_checksum = dkcksum(lp);
	if (installboot)
		readboot();
	for (i = 0; i < lab.d_npartitions; i++)
		if (lab.d_partitions[i].p_size)
			lab.d_partitions[i].p_offset += lba_offset;
	bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * lab.d_secsize,
	    lp);

	fd = open(specname, O_RDWR);
	if (fd < 0) {
		if (is_file) {
			warn("cannot open file %s for writing label", specname);
			return(1);
		} else
			serrno = errno;

		if (geom_class_available("PART") != 0) {
			/*
			 * Since we weren't able open provider for
			 * writing, then recommend user to use gpart(8).
			 */
			warnc(serrno,
			    "cannot open provider %s for writing label",
			    specname);
			warnx("Try to use gpart(8).");
			return (1);
		}

		/* Give up if GEOM_BSD is not available. */
		if (geom_class_available("BSD") == 0) {
			warnc(serrno, "%s", specname);
			return (1);
		}

		grq = gctl_get_handle();
		gctl_ro_param(grq, "verb", -1, "write label");
		gctl_ro_param(grq, "class", -1, "BSD");
		gctl_ro_param(grq, "geom", -1, pname);
		gctl_ro_param(grq, "label", 148+16*8,
			bootarea + labeloffset + labelsoffset * lab.d_secsize);
		errstr = gctl_issue(grq);
		if (errstr != NULL) {
			warnx("%s", errstr);
			gctl_free(grq);
			return(1);
		}
		gctl_free(grq);
		if (installboot) {
			grq = gctl_get_handle();
			gctl_ro_param(grq, "verb", -1, "write bootcode");
			gctl_ro_param(grq, "class", -1, "BSD");
			gctl_ro_param(grq, "geom", -1, pname);
			gctl_ro_param(grq, "bootcode", BBSIZE, bootarea);
			errstr = gctl_issue(grq);
			if (errstr != NULL) {
				warnx("%s", errstr);
				gctl_free(grq);
				return (1);
			}
			gctl_free(grq);
		}
	} else {
		if (write(fd, bootarea, bbsize) != bbsize) {
			warn("write %s", specname);
			close (fd);
			return (1);
		}
		close (fd);
	}
	return (0);
}
示例#24
0
void
gvinum_create(int argc, char **argv)
{
	struct gctl_req *req;
	struct gv_drive *d;
	struct gv_plex *p;
	struct gv_sd *s;
	struct gv_volume *v;
	FILE *tmp;
	int drives, errors, fd, flags, i, line, plexes, plex_in_volume;
	int sd_in_plex, status, subdisks, tokens, undeffd, volumes;
	const char *errstr;
	char buf[BUFSIZ], buf1[BUFSIZ], commandline[BUFSIZ], *ed, *sdname;
	char original[BUFSIZ], tmpfile[20], *token[GV_MAXARGS];
	char plex[GV_MAXPLEXNAME], volume[GV_MAXVOLNAME];

	tmp = NULL;
	flags = 0;
	for (i = 1; i < argc; i++) {
		/* Force flag used to ignore already created drives. */
		if (!strcmp(argv[i], "-f")) {
			flags |= GV_FLAG_F;
		/* Else it must be a file. */
		} else {
			if ((tmp = fopen(argv[1], "r")) == NULL) {
				warn("can't open '%s' for reading", argv[1]);
				return;
			}
		}	
	}

	/* We didn't get a file. */
	if (tmp == NULL) {
		snprintf(tmpfile, sizeof(tmpfile), "/tmp/gvinum.XXXXXX");
		
		if ((fd = mkstemp(tmpfile)) == -1) {
			warn("temporary file not accessible");
			return;
		}
		if ((tmp = fdopen(fd, "w")) == NULL) {
			warn("can't open '%s' for writing", tmpfile);
			return;
		}
		printconfig(tmp, "# ");
		fclose(tmp);
		
		ed = getenv("EDITOR");
		if (ed == NULL)
			ed = _PATH_VI;
		
		snprintf(commandline, sizeof(commandline), "%s %s", ed,
		    tmpfile);
		status = system(commandline);
		if (status != 0) {
			warn("couldn't exec %s; status: %d", ed, status);
			return;
		}
		
		if ((tmp = fopen(tmpfile, "r")) == NULL) {
			warn("can't open '%s' for reading", tmpfile);
			return;
		}
	}

	req = gctl_get_handle();
	gctl_ro_param(req, "class", -1, "VINUM");
	gctl_ro_param(req, "verb", -1, "create");
	gctl_ro_param(req, "flags", sizeof(int), &flags);

	drives = volumes = plexes = subdisks = 0;
	plex_in_volume = sd_in_plex = undeffd = 0;
	plex[0] = '\0';
	errors = 0;
	line = 1;
	while ((fgets(buf, BUFSIZ, tmp)) != NULL) {

		/* Skip empty lines and comments. */
		if (*buf == '\0' || *buf == '#') {
			line++;
			continue;
		}

		/* Kill off the newline. */
		buf[strlen(buf) - 1] = '\0';

		/*
		 * Copy the original input line in case we need it for error
		 * output.
		 */
		strlcpy(original, buf, sizeof(original));

		tokens = gv_tokenize(buf, token, GV_MAXARGS);
		if (tokens <= 0) {
			line++;
			continue;
		}

		/* Volume definition. */
		if (!strcmp(token[0], "volume")) {
			v = gv_new_volume(tokens, token);
			if (v == NULL) {
				warnx("line %d: invalid volume definition",
				    line);
				warnx("line %d: '%s'", line, original);
				errors++;
				line++;
				continue;
			}

			/* Reset plex count for this volume. */
			plex_in_volume = 0;

			/*
			 * Set default volume name for following plex
			 * definitions.
			 */
			strlcpy(volume, v->name, sizeof(volume));

			snprintf(buf1, sizeof(buf1), "volume%d", volumes);
			gctl_ro_param(req, buf1, sizeof(*v), v);
			volumes++;

		/* Plex definition. */
		} else if (!strcmp(token[0], "plex")) {
			p = gv_new_plex(tokens, token);
			if (p == NULL) {
				warnx("line %d: invalid plex definition", line);
				warnx("line %d: '%s'", line, original);
				errors++;
				line++;
				continue;
			}

			/* Reset subdisk count for this plex. */
			sd_in_plex = 0;

			/* Default name. */
			if (strlen(p->name) == 0) {
				snprintf(p->name, sizeof(p->name), "%s.p%d",
				    volume, plex_in_volume++);
			}

			/* Default volume. */
			if (strlen(p->volume) == 0) {
				snprintf(p->volume, sizeof(p->volume), "%s",
				    volume);
			}

			/*
			 * Set default plex name for following subdisk
			 * definitions.
			 */
			strlcpy(plex, p->name, sizeof(plex));

			snprintf(buf1, sizeof(buf1), "plex%d", plexes);
			gctl_ro_param(req, buf1, sizeof(*p), p);
			plexes++;

		/* Subdisk definition. */
		} else if (!strcmp(token[0], "sd")) {
			s = gv_new_sd(tokens, token);
			if (s == NULL) {
				warnx("line %d: invalid subdisk "
				    "definition:", line);
				warnx("line %d: '%s'", line, original);
				errors++;
				line++;
				continue;
			}

			/* Default name. */
			if (strlen(s->name) == 0) {
				if (strlen(plex) == 0) {
					sdname = find_name("gvinumsubdisk.p",
					    GV_TYPE_SD, GV_MAXSDNAME);
					snprintf(s->name, sizeof(s->name),
					    "%s.s%d", sdname, undeffd++);
					free(sdname);
				} else {
					snprintf(s->name, sizeof(s->name),
					    "%s.s%d",plex, sd_in_plex++);
				}
			}

			/* Default plex. */
			if (strlen(s->plex) == 0)
				snprintf(s->plex, sizeof(s->plex), "%s", plex);

			snprintf(buf1, sizeof(buf1), "sd%d", subdisks);
			gctl_ro_param(req, buf1, sizeof(*s), s);
			subdisks++;

		/* Subdisk definition. */
		} else if (!strcmp(token[0], "drive")) {
			d = gv_new_drive(tokens, token);
			if (d == NULL) {
				warnx("line %d: invalid drive definition:",
				    line);
				warnx("line %d: '%s'", line, original);
				errors++;
				line++;
				continue;
			}

			snprintf(buf1, sizeof(buf1), "drive%d", drives);
			gctl_ro_param(req, buf1, sizeof(*d), d);
			drives++;

		/* Everything else is bogus. */
		} else {
			warnx("line %d: invalid definition:", line);
			warnx("line %d: '%s'", line, original);
			errors++;
		}
		line++;
	}

	fclose(tmp);
	unlink(tmpfile);

	if (!errors && (volumes || plexes || subdisks || drives)) {
		gctl_ro_param(req, "volumes", sizeof(int), &volumes);
		gctl_ro_param(req, "plexes", sizeof(int), &plexes);
		gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
		gctl_ro_param(req, "drives", sizeof(int), &drives);
		errstr = gctl_issue(req);
		if (errstr != NULL)
			warnx("create failed: %s", errstr);
	}
	gctl_free(req);
}