Skip to content

Commit fa8eef0

Browse files
Damian-Nordickartben
authored andcommitted
settings: shell: improve reading and writing string values
Make reading and writing string values more flexible: 1. Eliminate the intermediate buffer when saving a string setting. This needlessly limited the maximum string length that could be saved using the shell command. 2. Do not add nor assume that a string saved in the settings includes the null-terminator. The settings subsystem uses metadata for encoding the value length, so there it is redundant to also store the null-terminator in flash. By the way, also make sure the command handlers only return -EINVAL and -ENOEXEC error codes as documented in the handler type description. Signed-off-by: Damian Krolik <[email protected]>
1 parent 766122f commit fa8eef0

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

subsys/settings/src/settings_shell.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <zephyr/sys/util.h>
1010
#include <zephyr/toolchain.h>
1111

12+
#include <ctype.h>
1213
#include <stdint.h>
1314
#include <stddef.h>
1415

@@ -51,6 +52,7 @@ static int cmd_list(const struct shell *shell_ptr, size_t argc, char *argv[])
5152

5253
if (err) {
5354
shell_error(shell_ptr, "Failed to load settings: %d", err);
55+
err = -ENOEXEC;
5456
}
5557

5658
return err;
@@ -74,6 +76,7 @@ static int settings_read_callback(const char *key,
7476
void *param)
7577
{
7678
uint8_t buffer[SETTINGS_MAX_VAL_LEN];
79+
ssize_t i;
7780
ssize_t num_read_bytes = MIN(len, SETTINGS_MAX_VAL_LEN);
7881
struct settings_read_callback_params *params = param;
7982

@@ -100,11 +103,13 @@ static int settings_read_callback(const char *key,
100103
shell_hexdump(params->shell_ptr, buffer, num_read_bytes);
101104
break;
102105
case SETTINGS_VALUE_STRING:
103-
if (buffer[num_read_bytes - 1] != '\0') {
104-
shell_error(params->shell_ptr, "Value is not a string");
105-
return 0;
106+
for (i = 0; i < num_read_bytes; i++) {
107+
if (!isprint(buffer[i])) {
108+
shell_error(params->shell_ptr, "Value is not a string");
109+
return 0;
110+
}
106111
}
107-
shell_print(params->shell_ptr, "%s", buffer);
112+
shell_print(params->shell_ptr, "%.*s", (int)num_read_bytes, buffer);
108113
break;
109114
}
110115

@@ -138,7 +143,7 @@ static int cmd_read(const struct shell *shell_ptr, size_t argc, char *argv[])
138143
err = settings_parse_type(argv[1], &value_type);
139144
if (err) {
140145
shell_error(shell_ptr, "Invalid type: %s", argv[1]);
141-
return err;
146+
return -EINVAL;
142147
}
143148
}
144149

@@ -152,9 +157,10 @@ static int cmd_read(const struct shell *shell_ptr, size_t argc, char *argv[])
152157

153158
if (err) {
154159
shell_error(shell_ptr, "Failed to load setting: %d", err);
160+
err = -ENOEXEC;
155161
} else if (!params.value_found) {
156-
err = -ENOENT;
157162
shell_error(shell_ptr, "Setting not found");
163+
err = -ENOEXEC;
158164
}
159165

160166
return err;
@@ -164,42 +170,39 @@ static int cmd_write(const struct shell *shell_ptr, size_t argc, char *argv[])
164170
{
165171
int err;
166172
uint8_t buffer[CONFIG_SHELL_CMD_BUFF_SIZE / 2];
167-
size_t buffer_len = 0;
173+
const void *value;
174+
size_t value_len = 0;
168175
enum settings_value_types value_type = SETTINGS_VALUE_HEX;
169176

170177
if (argc > 3) {
171178
err = settings_parse_type(argv[1], &value_type);
172179
if (err) {
173180
shell_error(shell_ptr, "Invalid type: %s", argv[1]);
174-
return err;
181+
return -EINVAL;
175182
}
176183
}
177184

178185
switch (value_type) {
179186
case SETTINGS_VALUE_HEX:
180-
buffer_len = hex2bin(argv[argc - 1], strlen(argv[argc - 1]),
181-
buffer, sizeof(buffer));
187+
value = buffer;
188+
value_len = hex2bin(argv[argc - 1], strlen(argv[argc - 1]), buffer, sizeof(buffer));
182189
break;
183190
case SETTINGS_VALUE_STRING:
184-
buffer_len = strlen(argv[argc - 1]) + 1;
185-
if (buffer_len > sizeof(buffer)) {
186-
shell_error(shell_ptr, "%s is bigger than shell's buffer", argv[argc - 1]);
187-
return -EINVAL;
188-
}
189-
190-
memcpy(buffer, argv[argc - 1], buffer_len);
191+
value = argv[argc - 1];
192+
value_len = strlen(argv[argc - 1]);
191193
break;
192194
}
193195

194-
if (buffer_len == 0) {
196+
if (value_len == 0) {
195197
shell_error(shell_ptr, "Failed to parse value");
196198
return -EINVAL;
197199
}
198200

199-
err = settings_save_one(argv[argc - 2], buffer, buffer_len);
201+
err = settings_save_one(argv[argc - 2], value, value_len);
200202

201203
if (err) {
202204
shell_error(shell_ptr, "Failed to write setting: %d", err);
205+
err = -ENOEXEC;
203206
}
204207

205208
return err;
@@ -213,6 +216,7 @@ static int cmd_delete(const struct shell *shell_ptr, size_t argc, char *argv[])
213216

214217
if (err) {
215218
shell_error(shell_ptr, "Failed to delete setting: %d", err);
219+
err = -ENOEXEC;
216220
}
217221

218222
return err;

0 commit comments

Comments
 (0)