xref: /freebsd/stand/common/nvstore.c (revision 02e9120893770924227138ba49df1edb3896112a)
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 
39 COMMAND_SET(nvstore, "nvstore", "manage non-volatile data", command_nvstore);
40 
41 static void
42 nvstore_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  */
58 static int
59 command_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