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