blob: 472ba2c28a0ef15c91ea4b3bef726668dffe23a2 [file] [log] [blame] [raw]
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015-2021 Rivoreo
*/
#define NEED_SOLARIS_BOOLEAN
#include <sys/types.h>
/*
#define B_FALSE 0
#define B_TRUE 1
typedef int boolean_t;
typedef unsigned int uint_t;
typedef unsigned char uchar_t;
typedef long long int hrtime_t;
*/
#ifdef __GLIBC__
typedef uint64_t rlim64_t;
#endif
#include <sys/list.h>
#include <libzfs.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
extern nvlist_t *nvlist_create_from_json(const char *);
extern nvlist_t *nvlist_create_from_json_fd(int);
#if 0
static const char config[] = "{\n"
" \"type\":\"root\",\n"
" \"children\":[\n"
" {\n"
" \"type\":\"mirror\",\n"
" \"children\":[\n"
" {\n"
" \"type\":\"file\",\n"
" \"path\":\"/mnt/net/test/hd0\"\n"
" },\n"
" {\n"
" \"type\":\"file\",\n"
" \"path\":\"/mnt/net/test/hd1\"\n"
" }\n"
" ]\n"
" },\n"
" {\n"
" \"type\":\"file\",\n"
" \"path\":\"/mnt/net/test/hd2\"\n"
" }\n"
" ]\n"
"}";
#endif
//static nvlist_t *create_nvlist_from_json(const char *s) {
//}
static void print_usage(const char *name) {
fprintf(stderr, "Usage: %s [-n] -N <pool-name> { -F {<config-json-file>|-[<fd>]} | -c <vdev-config-json>}\n", name);
}
static void print_vdev_tree(libzfs_handle_t *lzh, zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, boolean_t print_logs) {
nvlist_t **child;
uint_t c, children;
char *vname;
if (name != NULL)
(void) printf("\t%*s%s\n", indent, "", name);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
&child, &children) != 0)
return;
for (c = 0; c < children; c++) {
//fprintf(stderr, "print_vdev_tree: child[%u] = %p\n", c, child[c]);
uint64_t is_log = B_FALSE;
#if 1
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
&is_log);
#else
if(nvlist_exists_number(child[c], ZPOOL_CONFIG_IS_LOG)) {
is_log = nvlist_get_number(child[c], ZPOOL_CONFIG_IS_LOG);
}
#endif
if ((is_log && !print_logs) || (!is_log && print_logs))
continue;
vname = zpool_vdev_name(lzh, zhp, child[c], B_FALSE);
print_vdev_tree(lzh, zhp, vname, child[c], indent + 2,
B_FALSE);
free(vname);
}
}
int main(int argc, char **argv) {
const char *name = NULL;
const char *config_file = NULL;
const char *config = NULL;
int dryrun = 0;
while(1) {
int c = getopt(argc, argv, "c:F:nN:h");
if(c == -1) break;
switch(c) {
case 'c':
config = optarg;
break;
case 'F':
config_file = optarg;
break;
case 'n':
dryrun = 1;
break;
case 'N':
name = optarg;
break;
case 'h':
print_usage(argv[0]);
return 0;
case '?':
return -1;
}
}
if(!name) {
fprintf(stderr, "%s: missing pool name, please specify '-N'\n", argv[0]);
print_usage(argv[0]);
return -1;
}
if(!config_file && !config) {
fprintf(stderr, "%s: missing pool vdev configuration\n", argv[0]);
print_usage(argv[0]);
return -1;
}
if(config_file && config) {
fprintf(stderr, "%s: cannot specify both '-c' and '-F'\n", argv[0]);
return -1;
}
libzfs_handle_t *zfsh = libzfs_init();
if(!zfsh) {
perror("libzfs_init");
return 1;
}
libzfs_print_on_error(zfsh, 1);
nvlist_t *nvroot;
if(config_file) {
int fd;
if(*config_file == '-') {
const char *fdn = config_file + 1;
if(isdigit(*fdn)) {
char *end_p;
fd = strtol(fdn, &end_p, 10);
if(*end_p) goto open_from_file_name;
} else if(!*fdn) fd = STDIN_FILENO;
else goto open_from_file_name;
} else {
open_from_file_name:
fd = open(config_file, O_RDONLY);
if(fd == -1) {
perror(config_file);
return 1;
}
}
nvroot = nvlist_create_from_json_fd(fd);
} else {
nvroot = nvlist_create_from_json(config);
}
if(!nvroot) {
fputs("Invalid configurtion\n", stderr);
return 1;
}
print_vdev_tree(zfsh, NULL, name, nvroot, 0, 0);
if(dryrun) {
fputs("Exiting with dryrun\n", stderr);
return 0;
}
if(zpool_create(zfsh, name, nvroot, NULL, NULL) < 0) {
return 1;
}
//zfs_handle_t *pool = zfs_open(zfsh, name, ZFS_TYPE_FILESYSTEM);
return 0;
}