From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: From: Ahmad Fatoum Date: Thu, 8 Oct 2020 17:48:40 +0200 Message-Id: <20201008154840.21531-1-a.fatoum@pengutronix.de> MIME-Version: 1.0 Subject: [OSS-Tools] [PATCH] barebox-state: add new --update option to avoid writes if possible List-Id: Pengutronix Public Open-Source-Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: oss-tools-bounces@pengutronix.de Sender: "OSS-Tools" To: oss-tools@pengutronix.de barebox-state --set always writes the state when successful. Users seeking to conserve write cycles thus have to --get the variable in question first to check whether to write it. Make life of such users easier by having barebox-state support this out-of-the-box. Use of the new --update option will only write a variable if its new and old value compare unequal. This allows users to fire and forget execute barebox-state. Signed-off-by: Ahmad Fatoum --- src/barebox-state.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/barebox-state.c b/src/barebox-state.c index cd56ce7192c3..09e054e25f8b 100644 --- a/src/barebox-state.c +++ b/src/barebox-state.c @@ -51,6 +51,8 @@ static char *__state_mac_get(struct state_variable *var); static int __state_string_set(struct state_variable *var, const char *val); static char *__state_string_get(struct state_variable *var); +enum state_action { STATE_ACTION_GET, STATE_ACTION_SET, STATE_ACTION_UPDATE }; + struct variable_str_type { enum state_variable_type type; char *type_name; @@ -279,7 +281,8 @@ char *state_get_var(struct state *state, const char *var) return vtype->get(sv); } -static int state_set_var(struct state *state, const char *var, const char *val) +static int state_set_var(struct state *state, const char *var, const char *val, + enum state_action action) { struct state_variable *sv; struct variable_str_type *vtype; @@ -296,6 +299,18 @@ static int state_set_var(struct state *state, const char *var, const char *val) if (!vtype->set) return -EPERM; + if (action == STATE_ACTION_UPDATE) { + char *oldval = vtype->get(sv); + + if (!IS_ERR(oldval)) { + if (!strcmp(oldval, val)) { + free(oldval); + return 0; + } + free(oldval); + } + } + ret = vtype->set(sv, val); if (ret) return ret; @@ -387,6 +402,7 @@ enum opt { static struct option long_options[] = { {"get", required_argument, 0, 'g' }, {"set", required_argument, 0, 's' }, + {"update", required_argument, 0, 'u' }, {"name", required_argument, 0, 'n' }, {"input", required_argument, 0, 'i' }, {"dump", no_argument, 0, 'd' }, @@ -407,6 +423,7 @@ static void usage(char *name) "\n" "-g, --get get the value of a variable\n" "-s, --set = set the value of a variable\n" +"-u, --update = update the value of a variable only if it changed\n" "-n, --name specify the state to use (default=\"state\"). Multiple states are allowed.\n" "-i, --input load the devicetree from a file instead of using the system devicetree.\n" "-d, --dump dump the state\n" @@ -425,7 +442,7 @@ static void usage(char *name) struct state_set_get { char *arg; - int get; + enum state_action action; struct list_head list; }; @@ -456,7 +473,7 @@ int main(int argc, char *argv[]) INIT_LIST_HEAD(&state_list.list); while (1) { - c = getopt_long(argc, argv, "hg:s:i:dvn:qf", long_options, &option_index); + c = getopt_long(argc, argv, "hg:u:s:i:dvn:qf", long_options, &option_index); if (c < 0) break; switch (c) { @@ -468,13 +485,14 @@ int main(int argc, char *argv[]) exit(0); case 'g': sg = xzalloc(sizeof(*sg)); - sg->get = 1; + sg->action = STATE_ACTION_GET; sg->arg = optarg; list_add_tail(&sg->list, &sg_list); break; + case 'u': case 's': sg = xzalloc(sizeof(*sg)); - sg->get = 0; + sg->action = c == 's' ? STATE_ACTION_SET : STATE_ACTION_UPDATE; sg->arg = optarg; list_add_tail(&sg->list, &sg_list); readonly = false; @@ -627,7 +645,7 @@ int main(int argc, char *argv[]) if (state == &state_list) { state = list_first_entry(&state_list.list, struct state_list, list); } - if (sg->get) { + if (sg->action == STATE_ACTION_GET) { char *val = state_get_var(state->state, arg); if (!val) { pr_err("no such variable: %s\n", arg); @@ -647,7 +665,7 @@ int main(int argc, char *argv[]) goto out_unlock; } *val++ = '\0'; - ret = state_set_var(state->state, var, val); + ret = state_set_var(state->state, var, val, sg->action); if (ret) { pr_err("Failed to set variable %s in state %s to %s: %s\n", var, state->name, val, -- 2.28.0 _______________________________________________ OSS-Tools mailing list OSS-Tools@pengutronix.de