1/*-
2 * Copyright 2020 Toomas Soome <tsoome@me.com>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26/*
27 * Big Theory Statement.
28 *
29 * nvstore is abstraction layer to implement data read/write to different
30 * types of non-volatile storage.
31 *
32 * Provides cli command 'nvostre'
33 */
34
35#include "stand.h"
36#include "nvstore.h"
37#include "bootstrap.h"
38
39COMMAND_SET(nvstore, "nvstore", "manage non-volatile data", command_nvstore);
40
41static void
42nvstore_usage(const char *me)
43{
44	printf("Usage:\t%s -l\n", me);
45	printf("\t%s store -l\n", me);
46	printf("\t%s store [-t type] key value\n", me);
47	printf("\t%s store -g key\n", me);
48	printf("\t%s store -d key\n", me);
49}
50
51/*
52 * Usage: nvstore -l		# list stores
53 *	nvstore store -l	# list data in store
54 *	nvstore store [-t type] key value
55 *	nvstore store -g key	# get value
56 *	nvstore store -d key	# delete key
57 */
58static int
59command_nvstore(int argc, char *argv[])
60{
61	int c;
62	bool list, get, delete;
63	nvstore_t *st;
64	char *me, *name, *type;
65
66	me = argv[0];
67	optind = 1;
68	optreset = 1;
69
70	list = false;
71	while ((c = getopt(argc, argv, "l")) != -1) {
72		switch (c) {
73		case 'l':
74			list = true;
75			break;
76		case '?':
77		default:
78			return (CMD_ERROR);
79		}
80	}
81
82	argc -= optind;
83	argv += optind;
84
85	if (argc == 0) {
86		if (list) {
87			if (STAILQ_EMPTY(&stores)) {
88				printf("No configured nvstores\n");
89				return (CMD_OK);
90			}
91			printf("List of configured nvstores:\n");
92			STAILQ_FOREACH(st, &stores, nvs_next) {
93				printf("\t%s\n", st->nvs_name);
94			}
95			return (CMD_OK);
96		}
97		nvstore_usage(me);
98		return (CMD_ERROR);
99	}
100
101	if (argc == 0 || (argc != 0 && list)) {
102		nvstore_usage(me);
103		return (CMD_ERROR);
104	}
105
106	st = nvstore_get_store(argv[0]);
107	if (st == NULL) {
108		nvstore_usage(me);
109		return (CMD_ERROR);
110	}
111
112	optind = 1;
113	optreset = 1;
114	name = NULL;
115	type = NULL;
116	get = delete = false;
117
118	while ((c = getopt(argc, argv, "d:g:lt:")) != -1) {
119		switch (c) {
120		case 'd':
121			if (list || get) {
122				nvstore_usage(me);
123				return (CMD_ERROR);
124			}
125			name = optarg;
126			delete = true;
127			break;
128		case 'g':
129			if (delete || list) {
130				nvstore_usage(me);
131				return (CMD_ERROR);
132			}
133			name = optarg;
134			get = true;
135			break;
136		case 'l':
137			if (delete || get) {
138				nvstore_usage(me);
139				return (CMD_ERROR);
140			}
141			list = true;
142			break;
143		case 't':
144			type = optarg;
145			break;
146		case '?':
147		default:
148			return (CMD_ERROR);
149		}
150	}
151
152	argc -= optind;
153	argv += optind;
154
155	if (list) {
156		(void) nvstore_print(st);
157		return (CMD_OK);
158	}
159
160	if (delete && name != NULL) {
161		(void) nvstore_unset_var(st, name);
162		return (CMD_OK);
163	}
164
165	if (get && name != NULL) {
166		char *ptr = NULL;
167
168		if (nvstore_get_var(st, name, (void **)&ptr) == 0)
169			printf("%s = %s\n", name, ptr);
170		return (CMD_OK);
171	}
172
173	if (argc == 2) {
174		c = nvstore_set_var_from_string(st, type, argv[0], argv[1]);
175		if (c != 0) {
176			printf("error: %s\n", strerror(c));
177			return (CMD_ERROR);
178		}
179		return (CMD_OK);
180	}
181
182	nvstore_usage(me);
183	return (CMD_OK);
184}
185