env: add env_update()

This add/append/replace the sub value of an environment variable.

Change-Id: I0fcda0a1c631013eb9458a04a09546ba1c643db3
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2017-09-27 14:23:25 +08:00 committed by Kever Yang
parent fafee76a04
commit 64c74e0b2d
2 changed files with 227 additions and 0 deletions

View File

@ -297,6 +297,222 @@ int env_set(const char *varname, const char *varvalue)
return _do_env_set(0, 3, (char * const *)argv, H_PROGRAMMATIC);
}
static int env_append(const char *varname, const char *varvalue)
{
int len = 0;
char *oldvalue, *newvalue;
/* before import into hashtable */
if (!(gd->flags & GD_FLG_ENV_READY) || !varname)
return 1;
if (varvalue)
len += strlen(varvalue);
oldvalue = env_get(varname);
if (oldvalue) {
len += strlen(oldvalue);
/* Exist ! */
if (strstr(oldvalue, varvalue))
return 0;
}
newvalue = malloc(len + 2);
if (!newvalue) {
printf("Error: malloc in %s failed!\n", __func__);
return 1;
}
*newvalue = '\0';
if (oldvalue) {
strcpy(newvalue, oldvalue);
strcat(newvalue, " ");
}
if (varvalue)
strcat(newvalue, varvalue);
env_set(varname, newvalue);
free(newvalue);
return 0;
}
static int env_replace(const char *varname, const char *substr,
const char *replacement)
{
char *oldvalue, *newvalue, *dst, *sub;
int substr_len, replace_len, oldvalue_len, len;
/* before import into hashtable */
if (!(gd->flags & GD_FLG_ENV_READY) || !varname)
return 1;
oldvalue = env_get(varname);
if (!oldvalue)
return 1;
sub = strstr(oldvalue, substr);
if (!sub)
return 1;
oldvalue_len = strlen(oldvalue) + 1;
substr_len = strlen(substr);
replace_len = strlen(replacement);
if (replace_len >= substr_len)
len = oldvalue_len + replace_len - substr_len;
else
len = oldvalue_len + substr_len - replace_len;
newvalue = malloc(len);
if (!newvalue) {
printf("Error: malloc in %s failed!\n", __func__);
return 1;
}
*newvalue = '\0';
/*
* Orignal string is splited like format: [str1.. substr str2..]
*/
/* str1.. */
dst = newvalue;
dst = strncat(dst, oldvalue, sub - oldvalue);
/* substr */
dst += sub - oldvalue;
dst = strncat(dst, replacement, replace_len);
/* str2.. */
dst += replace_len;
len = oldvalue_len - substr_len - (sub - oldvalue);
dst = strncat(dst, sub + substr_len, len);
env_set(varname, newvalue);
free(newvalue);
return 0;
}
#define ARGS_ITEM_NUM 50
int env_update(const char *varname, char *varvalue)
{
/* 'a_' means "varargs_'; 'v_' means 'varvalue_' */
char *varargs;
char *a_title, *v_title;
char *a_string_tok, *a_item_tok = NULL;
char *v_string_tok, *v_item_tok = NULL;
char *a_item, *a_items[ARGS_ITEM_NUM] = { NULL };
char *v_item, *v_items[ARGS_ITEM_NUM] = { NULL };
bool match = false;
int i = 0, j = 0;
/* Before import into hashtable */
if (!(gd->flags & GD_FLG_ENV_READY) || !varname)
return 1;
/* If varname doesn't exist, create it and set varvalue */
varargs = env_get(varname);
if (!varargs) {
env_set(varname, varvalue);
return 0;
}
/* Malloc a temporary varargs for strtok */
a_string_tok = strdup(varargs);
if (!a_string_tok) {
printf("Error: strdup in failed, line=%d\n", __LINE__);
return 1;
}
/* Malloc a temporary varvalue for strtok */
v_string_tok = strdup(varvalue);
if (!v_string_tok) {
free(a_string_tok);
printf("Error: strdup in failed, line=%d\n", __LINE__);
return 1;
}
/* Splite varargs into items containing "=" by the blank */
a_item = strtok(a_string_tok, " ");
while (a_item && i < ARGS_ITEM_NUM) {
debug("%s: [a_item %d]: %s\n", __func__, i, a_item);
if (strstr(a_item, "="))
a_items[i++] = a_item;
a_item = strtok(NULL, " ");
}
/*
* Splite varvalue into items containing "=" by the blank.
* parse varvalue title, eg: "bootmode=emmc", title is "bootmode"
*/
v_item = strtok(v_string_tok, " ");
while (v_item && j < ARGS_ITEM_NUM) {
debug("%s: <v_item %d>: %s\n", __func__, j, v_item);
if (strstr(v_item, "="))
v_items[j++] = v_item;
else
env_append(varname, v_item);
v_item = strtok(NULL, " ");
}
/* For every v_item, search its title */
for (j = 0; j < ARGS_ITEM_NUM && v_items[j]; j++) {
v_item = v_items[j];
/* Malloc a temporary a_item for strtok */
v_item_tok = strdup(v_item);
if (!v_item_tok) {
printf("Error: strdup in failed, line=%d\n", __LINE__);
free(a_string_tok);
free(v_string_tok);
return 1;
}
v_title = strtok(v_item_tok, "=");
debug("%s: <v_title>: %s\n", __func__, v_title);
/* For every a_item, search its title */
for (i = 0; i < ARGS_ITEM_NUM && a_items[i]; i++) {
a_item = a_items[i];
/* Malloc a temporary a_item for strtok */
a_item_tok = strdup(a_item);
if (!a_item_tok) {
printf("Error: strdup in failed, line=%d\n", __LINE__);
free(a_string_tok);
free(v_string_tok);
free(v_item_tok);
return 1;
}
a_title = strtok(a_item_tok, "=");
debug("%s: [a_title]: %s\n", __func__, a_title);
if (!strcmp(a_title, v_title)) {
/* Find! replace it */
env_replace(varname, a_item, v_item);
free(a_item_tok);
match = true;
break;
}
free(a_item_tok);
}
/* Not find, just append */
if (!match)
env_append(varname, v_item);
match = false;
free(v_item_tok);
}
free(v_string_tok);
free(a_string_tok);
return 0;
}
/**
* Set an environment variable to an integer value
*

View File

@ -378,6 +378,17 @@ int env_get_yesno(const char *var);
*/
int env_set(const char *varname, const char *value);
/**
* env_update() - update sub value of an environment variable
*
* This add/append/replace the sub value of an environment variable.
*
* @varname: Variable to adjust
* @valude: Value to append/replace
* @return 0 if OK, 1 on error
*/
int env_update(const char *varname, char *varvalue);
/**
* env_set_ulong() - set an environment variable to an integer
*