1308089Savg/*-
2308089Savg * Copyright (c) 2016 Andriy Gapon <avg@FreeBSD.org>
3308089Savg * All rights reserved.
4308089Savg *
5308089Savg * Redistribution and use in source and binary forms, with or without
6308089Savg * modification, are permitted provided that the following conditions
7308089Savg * are met:
8308089Savg * 1. Redistributions of source code must retain the above copyright
9308089Savg *    notice, this list of conditions and the following disclaimer.
10308089Savg * 2. Redistributions in binary form must reproduce the above copyright
11308089Savg *    notice, this list of conditions and the following disclaimer in the
12308089Savg *    documentation and/or other materials provided with the distribution.
13308089Savg *
14308089Savg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15308089Savg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16308089Savg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17308089Savg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18308089Savg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19308089Savg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20308089Savg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21308089Savg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22308089Savg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23308089Savg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24308089Savg */
25308089Savg
26308089Savg#include <sys/cdefs.h>
27308089Savg__FBSDID("$FreeBSD: stable/11/sbin/zfsbootcfg/zfsbootcfg.c 308089 2016-10-29 14:09:32Z avg $");
28308089Savg
29308089Savg#include <sys/types.h>
30308089Savg#include <errno.h>
31308089Savg#include <limits.h>
32308089Savg#include <inttypes.h>
33308089Savg#include <stdio.h>
34308089Savg#include <stdlib.h>
35308089Savg#include <string.h>
36308089Savg#include <kenv.h>
37308089Savg
38308089Savg#include <libzfs.h>
39308089Savg
40308089Savg/* Keep in sync with zfsboot.c. */
41308089Savg#define MAX_COMMAND_LEN	512
42308089Savg
43308089Savgint main(int argc, const char * const *argv)
44308089Savg{
45308089Savg	char buf[32];
46308089Savg	libzfs_handle_t *hdl;
47308089Savg	uint64_t pool_guid;
48308089Savg	uint64_t vdev_guid;
49308089Savg	int zfs_fd;
50308089Savg	int len;
51308089Savg
52308089Savg	if (argc != 2) {
53308089Savg		fprintf(stderr, "usage: zfsbootcfg <boot.config(5) options>\n");
54308089Savg		return (1);
55308089Savg	}
56308089Savg
57308089Savg	len = strlen(argv[1]);
58308089Savg	if (len >= MAX_COMMAND_LEN) {
59308089Savg		fprintf(stderr, "options string is too long\n");
60308089Savg		return (1);
61308089Savg	}
62308089Savg
63308089Savg	if (kenv(KENV_GET, "vfs.zfs.boot.primary_pool", buf, sizeof(buf)) <= 0) {
64308089Savg		perror("can't get vfs.zfs.boot.primary_pool");
65308089Savg		return (1);
66308089Savg	}
67308089Savg	pool_guid = strtoumax(buf, NULL, 10);
68308089Savg	if (pool_guid == 0) {
69308089Savg		perror("can't parse vfs.zfs.boot.primary_pool");
70308089Savg		return (1);
71308089Savg	}
72308089Savg
73308089Savg	if (kenv(KENV_GET, "vfs.zfs.boot.primary_vdev", buf, sizeof(buf)) <= 0) {
74308089Savg		perror("can't get vfs.zfs.boot.primary_vdev");
75308089Savg		return (1);
76308089Savg	}
77308089Savg	vdev_guid = strtoumax(buf, NULL, 10);
78308089Savg	if (vdev_guid == 0) {
79308089Savg		perror("can't parse vfs.zfs.boot.primary_vdev");
80308089Savg		return (1);
81308089Savg	}
82308089Savg
83308089Savg	if ((hdl = libzfs_init()) == NULL) {
84308089Savg		(void) fprintf(stderr, "internal error: failed to "
85308089Savg		    "initialize ZFS library\n");
86308089Savg		return (1);
87308089Savg	}
88308089Savg
89308089Savg	if (zpool_nextboot(hdl, pool_guid, vdev_guid, argv[1]) != 0) {
90308089Savg		perror("ZFS_IOC_NEXTBOOT failed");
91308089Savg		libzfs_fini(hdl);
92308089Savg		return (1);
93308089Savg	}
94308089Savg
95308089Savg	libzfs_fini(hdl);
96308089Savg	printf("zfs next boot options are successfully written\n");
97308089Savg	return (0);
98308089Savg}
99