xref: /freebsd/sbin/zfsbootcfg/zfsbootcfg.c (revision 97371ba2a9bd423f6a8742e06dc2b7c68b7cf5d2)
1*97371ba2SAndriy Gapon /*-
2*97371ba2SAndriy Gapon  * Copyright (c) 2016 Andriy Gapon <avg@FreeBSD.org>
3*97371ba2SAndriy Gapon  * All rights reserved.
4*97371ba2SAndriy Gapon  *
5*97371ba2SAndriy Gapon  * Redistribution and use in source and binary forms, with or without
6*97371ba2SAndriy Gapon  * modification, are permitted provided that the following conditions
7*97371ba2SAndriy Gapon  * are met:
8*97371ba2SAndriy Gapon  * 1. Redistributions of source code must retain the above copyright
9*97371ba2SAndriy Gapon  *    notice, this list of conditions and the following disclaimer.
10*97371ba2SAndriy Gapon  * 2. Redistributions in binary form must reproduce the above copyright
11*97371ba2SAndriy Gapon  *    notice, this list of conditions and the following disclaimer in the
12*97371ba2SAndriy Gapon  *    documentation and/or other materials provided with the distribution.
13*97371ba2SAndriy Gapon  *
14*97371ba2SAndriy Gapon  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*97371ba2SAndriy Gapon  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*97371ba2SAndriy Gapon  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*97371ba2SAndriy Gapon  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18*97371ba2SAndriy Gapon  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*97371ba2SAndriy Gapon  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*97371ba2SAndriy Gapon  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*97371ba2SAndriy Gapon  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*97371ba2SAndriy Gapon  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*97371ba2SAndriy Gapon  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*97371ba2SAndriy Gapon  */
25*97371ba2SAndriy Gapon 
26*97371ba2SAndriy Gapon #include <sys/cdefs.h>
27*97371ba2SAndriy Gapon __FBSDID("$FreeBSD$");
28*97371ba2SAndriy Gapon 
29*97371ba2SAndriy Gapon #include <sys/types.h>
30*97371ba2SAndriy Gapon #include <errno.h>
31*97371ba2SAndriy Gapon #include <limits.h>
32*97371ba2SAndriy Gapon #include <inttypes.h>
33*97371ba2SAndriy Gapon #include <stdio.h>
34*97371ba2SAndriy Gapon #include <stdlib.h>
35*97371ba2SAndriy Gapon #include <string.h>
36*97371ba2SAndriy Gapon #include <kenv.h>
37*97371ba2SAndriy Gapon 
38*97371ba2SAndriy Gapon #include <libzfs.h>
39*97371ba2SAndriy Gapon 
40*97371ba2SAndriy Gapon /* Keep in sync with zfsboot.c. */
41*97371ba2SAndriy Gapon #define MAX_COMMAND_LEN	512
42*97371ba2SAndriy Gapon 
43*97371ba2SAndriy Gapon int main(int argc, const char * const *argv)
44*97371ba2SAndriy Gapon {
45*97371ba2SAndriy Gapon 	char buf[32];
46*97371ba2SAndriy Gapon 	libzfs_handle_t *hdl;
47*97371ba2SAndriy Gapon 	uint64_t pool_guid;
48*97371ba2SAndriy Gapon 	uint64_t vdev_guid;
49*97371ba2SAndriy Gapon 	int zfs_fd;
50*97371ba2SAndriy Gapon 	int len;
51*97371ba2SAndriy Gapon 
52*97371ba2SAndriy Gapon 	if (argc != 2) {
53*97371ba2SAndriy Gapon 		fprintf(stderr, "usage: zfsbootcfg <boot.config(5) options>\n");
54*97371ba2SAndriy Gapon 		return (1);
55*97371ba2SAndriy Gapon 	}
56*97371ba2SAndriy Gapon 
57*97371ba2SAndriy Gapon 	len = strlen(argv[1]);
58*97371ba2SAndriy Gapon 	if (len >= MAX_COMMAND_LEN) {
59*97371ba2SAndriy Gapon 		fprintf(stderr, "options string is too long\n");
60*97371ba2SAndriy Gapon 		return (1);
61*97371ba2SAndriy Gapon 	}
62*97371ba2SAndriy Gapon 
63*97371ba2SAndriy Gapon 	if (kenv(KENV_GET, "vfs.zfs.boot.primary_pool", buf, sizeof(buf)) <= 0) {
64*97371ba2SAndriy Gapon 		perror("can't get vfs.zfs.boot.primary_pool");
65*97371ba2SAndriy Gapon 		return (1);
66*97371ba2SAndriy Gapon 	}
67*97371ba2SAndriy Gapon 	pool_guid = strtoumax(buf, NULL, 10);
68*97371ba2SAndriy Gapon 	if (pool_guid == 0) {
69*97371ba2SAndriy Gapon 		perror("can't parse vfs.zfs.boot.primary_pool");
70*97371ba2SAndriy Gapon 		return (1);
71*97371ba2SAndriy Gapon 	}
72*97371ba2SAndriy Gapon 
73*97371ba2SAndriy Gapon 	if (kenv(KENV_GET, "vfs.zfs.boot.primary_vdev", buf, sizeof(buf)) <= 0) {
74*97371ba2SAndriy Gapon 		perror("can't get vfs.zfs.boot.primary_vdev");
75*97371ba2SAndriy Gapon 		return (1);
76*97371ba2SAndriy Gapon 	}
77*97371ba2SAndriy Gapon 	vdev_guid = strtoumax(buf, NULL, 10);
78*97371ba2SAndriy Gapon 	if (vdev_guid == 0) {
79*97371ba2SAndriy Gapon 		perror("can't parse vfs.zfs.boot.primary_vdev");
80*97371ba2SAndriy Gapon 		return (1);
81*97371ba2SAndriy Gapon 	}
82*97371ba2SAndriy Gapon 
83*97371ba2SAndriy Gapon 	if ((hdl = libzfs_init()) == NULL) {
84*97371ba2SAndriy Gapon 		(void) fprintf(stderr, "internal error: failed to "
85*97371ba2SAndriy Gapon 		    "initialize ZFS library\n");
86*97371ba2SAndriy Gapon 		return (1);
87*97371ba2SAndriy Gapon 	}
88*97371ba2SAndriy Gapon 
89*97371ba2SAndriy Gapon 	if (zpool_nextboot(hdl, pool_guid, vdev_guid, argv[1]) != 0) {
90*97371ba2SAndriy Gapon 		perror("ZFS_IOC_NEXTBOOT failed");
91*97371ba2SAndriy Gapon 		libzfs_fini(hdl);
92*97371ba2SAndriy Gapon 		return (1);
93*97371ba2SAndriy Gapon 	}
94*97371ba2SAndriy Gapon 
95*97371ba2SAndriy Gapon 	libzfs_fini(hdl);
96*97371ba2SAndriy Gapon 	printf("zfs next boot options are successfully written\n");
97*97371ba2SAndriy Gapon 	return (0);
98*97371ba2SAndriy Gapon }
99