Failed to fetch fork details. Try again later.
-
终究还是我们队 authorede5b06d9b
Forked from
终究还是我们队 / proj235-Linux的OTA升级系统
Source project has a limited visibility.
#include "bootloader.h"
#include "grub.h"
static int grubenv_open(struct grubenv_t *grubenv)
{
FILE *fp = NULL;
size_t size;
int ret = 0;
char *buf = NULL, *key = NULL, *value = NULL;
fp = fopen(GRUBENV_PATH, "rb");
if (!fp) {
ERROR("Failed to open grubenv file: %s", GRUBENV_PATH);
ret = -1;
goto cleanup;
}
if (fseek(fp, 0, SEEK_END)) {
ERROR("Failed to seek end grubenv file: %s", GRUBENV_PATH);
ret = -1;
goto cleanup;
}
size = (size_t)ftell(fp);
if (size != GRUBENV_SIZE) {
ERROR("Invalid grubenv file size: %d", (int)size);
ret = -1;
goto cleanup;
}
if (fseek(fp, 0, SEEK_SET)) {
ERROR("Failed to seek set grubenv file: %s", GRUBENV_PATH);
ret = -1;
goto cleanup;
}
buf = calloc(1, size + 1);
if (!buf) {
ERROR("Not enough memory for environment");
ret = -ENOMEM;
goto cleanup;
}
if (fread(buf, 1, size, fp) != size) {
ERROR("Failed to read file %s", GRUBENV_PATH);
ret = 1;
goto cleanup;
}
if (memcmp(buf, GRUBENV_HEADER, strlen(GRUBENV_HEADER) -1)) {
ERROR("Invalid grubenv header");
ret = -1;
goto cleanup;
}
char *entry = buf;
char *p_char = buf;
while(*p_char != '\0') {
if (*p_char != '\n') {
p_char++;
continue;
}
if (*entry == '#') {
entry = p_char + 1;
p_char++;
continue;
}
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
key = strtok(entry, "=");
value = strtok(NULL, "\n");
if (value != NULL && key != NULL) {
ret = dict_set_value(&grubenv->vars, key, value);
if (ret) {
ERROR("Adding pair [%s] = %s into dictionary list"
"failed\n", key, value);
return ret;
}
}
entry = p_char + 1;
p_char++;
}
cleanup:
if (fp) fclose(fp);
free(buf);
return ret;
}
static int grubenv_parse_script(struct grubenv_t *grubenv, const char *script)
{
FILE *fp = NULL;
int ret = 0;
char *line = NULL, *key = NULL, *value = NULL;
size_t len = 0;
fp = fopen(script, "rb");
if (!fp) {
ERROR("Failed to open grubenv script file: %s", script);
ret = -1;
goto cleanup;
}
while ((getline(&line, &len, fp)) != -1) {
key = strtok(line, "=");
value = strtok(NULL, "\t\n");
if (value != NULL && key != NULL) {
ret = dict_set_value(&grubenv->vars, key, value);
if (ret) {
ERROR("Adding pair [%s] = %s into dictionary"
"list failed\n", key, value);
goto cleanup;
}
}
}
cleanup:
if (fp) fclose(fp);
free(line);
return ret;
}
static inline void grubenv_update_size(struct grubenv_t *grubenv)
{
int size = 0;
struct dict_entry *grubvar;
LIST_FOREACH(grubvar, &grubenv->vars, next) {
char *key = dict_entry_get_key(grubvar);
char *value = dict_entry_get_value(grubvar);
size = size + strlen(key) + strlen(value) + 2;
}
size += strlen(GRUBENV_HEADER);
grubenv->size = size;
}
static int grubenv_write(struct grubenv_t *grubenv)
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
{
FILE *fp = NULL;
char *buf = NULL, *ptr;
struct dict_entry *grubvar;
int ret = 0, llen = 0;
grubenv_update_size(grubenv);
if (grubenv->size > GRUBENV_SIZE) {
ERROR("Not enough free space in envblk file, %ld",
grubenv->size);
ret = -1;
goto cleanup;
}
fp = fopen(GRUBENV_PATH_NEW, "wb");
if (!fp) {
ERROR("Failed to open file: %s", GRUBENV_PATH_NEW);
ret = -1;
goto cleanup;
}
buf = malloc(GRUBENV_SIZE);
if (!buf) {
ERROR("Not enough memory for environment");
ret = -ENOMEM;
goto cleanup;
}
strncpy(buf, GRUBENV_HEADER, strlen(GRUBENV_HEADER) + 1);
LIST_FOREACH(grubvar, &grubenv->vars, next) {
char *key = dict_entry_get_key(grubvar);
char *value = dict_entry_get_value(grubvar);
char *tmp;
llen = strlen(key) + strlen(value) + 2;
ret = asprintf(&tmp, "%s=%s\n", key, value);
if (ret == ENOMEM_ASPRINTF) {
ERROR("OOM when copying Grub Env");
goto cleanup;
}
strncat(buf, tmp, llen);
free(tmp);
}
ptr = buf + grubenv->size;
memset(ptr, '#', buf + GRUBENV_SIZE - ptr);
ret = fwrite(buf , 1, GRUBENV_SIZE, fp);
if (ret != GRUBENV_SIZE) {
ERROR("Failed to write file: %s. Bytes written: %d",
GRUBENV_PATH_NEW, ret);
ret = -1;
goto cleanup;
}
cleanup:
if (fp) fclose(fp);
free(buf);
return ret;
}
static inline void grubenv_close(struct grubenv_t *grubenv)
{
dict_drop_db(&grubenv->vars);
}
static int do_env_set(const char *name, const char *value)