ret = xbc_init(*buf, size, &msg, NULL); /* Wrong data */ if (ret < 0) {
pr_err("parse error: %s.\n", msg); return ret;
}
return size;
}
staticvoid show_xbc_error(constchar *data, constchar *msg, int pos)
{ int lin = 1, col, i;
if (pos < 0) {
pr_err("Error: %s.\n", msg); return;
}
/* Note that pos starts from 0 but lin and col should start from 1. */
col = pos + 1; for (i = 0; i < pos; i++) { if (data[i] == '\n') {
lin++;
col = pos - i;
}
}
pr_err("Parse Error: %s at %d:%d\n", msg, lin, col);
}
staticint init_xbc_with_error(char *buf, int len)
{ char *copy = strdup(buf); constchar *msg; int ret, pos;
if (!copy) return -ENOMEM;
ret = xbc_init(buf, len, &msg, &pos); if (ret < 0)
show_xbc_error(copy, msg, pos);
free(copy);
return ret;
}
staticint show_xbc(constchar *path, bool list)
{ int ret, fd; char *buf = NULL; struct stat st;
ret = stat(path, &st); if (ret < 0) {
ret = -errno;
pr_err("Failed to stat %s: %d\n", path, ret); return ret;
}
fd = open(path, O_RDONLY); if (fd < 0) {
ret = -errno;
pr_err("Failed to open initrd %s: %d\n", path, ret); return ret;
}
ret = load_xbc_from_initrd(fd, &buf);
close(fd); if (ret < 0) {
pr_err("Failed to load a boot config from initrd: %d\n", ret); goto out;
} /* Assume a bootconfig file if it is enough small */ if (ret == 0 && st.st_size <= XBC_DATA_MAX) {
ret = load_xbc_file(path, &buf); if (ret < 0) {
pr_err("Failed to load a boot config: %d\n", ret); goto out;
} if (init_xbc_with_error(buf, ret) < 0) goto out;
} if (list)
xbc_show_list(); else
xbc_show_compact_tree();
ret = 0;
out:
free(buf);
return ret;
}
staticint delete_xbc(constchar *path)
{ struct stat stat; int ret = 0, fd, size; char *buf = NULL;
fd = open(path, O_RDWR); if (fd < 0) {
ret = -errno;
pr_err("Failed to open initrd %s: %d\n", path, ret); return ret;
}
size = load_xbc_from_initrd(fd, &buf); if (size < 0) {
ret = size;
pr_err("Failed to load a boot config from initrd: %d\n", ret);
} elseif (size > 0) {
ret = fstat(fd, &stat); if (!ret)
ret = ftruncate(fd, stat.st_size
- size - BOOTCONFIG_FOOTER_SIZE); if (ret)
ret = -errno;
} /* Ignore if there is no boot config in initrd */
/* TODO: Check the options by schema */
xbc_exit();
free(buf);
/* Remove old boot config if exists */
ret = delete_xbc(path); if (ret < 0) {
pr_err("Failed to delete previous boot config: %d\n", ret);
free(data); return ret;
}
/* Apply new one */
fd = open(path, O_RDWR | O_APPEND); if (fd < 0) {
ret = -errno;
pr_err("Failed to open %s: %d\n", path, ret);
free(data); return ret;
} /* TODO: Ensure the @path is initramfs/initrd image */ if (fstat(fd, &stat) < 0) {
ret = -errno;
pr_err("Failed to get the size of %s\n", path); goto out;
}
/* To align up the total size to BOOTCONFIG_ALIGN, get padding size */
total_size = stat.st_size + size + BOOTCONFIG_FOOTER_SIZE;
pad = ((total_size + BOOTCONFIG_ALIGN - 1) & (~BOOTCONFIG_ALIGN_MASK)) - total_size;
size += pad;
ret = write(fd, data, total_size); if (ret < total_size) { if (ret < 0)
ret = -errno;
pr_err("Failed to apply a boot config: %d\n", ret); if (ret >= 0) goto out_rollback;
} else
ret = 0;
out:
close(fd);
free(data);
return ret;
out_rollback: /* Map the partial write to -ENOSPC */ if (ret >= 0)
ret = -ENOSPC; if (ftruncate(fd, stat.st_size) < 0) {
ret = -errno;
pr_err("Failed to rollback the write error: %d\n", ret);
pr_err("The initrd %s may be corrupted. Recommend to rebuild.\n", path);
} goto out;
}
staticint usage(void)
{
printf("Usage: bootconfig [OPTIONS] \n" "Or bootconfig \n" " Apply, delete or show boot config to initrd.\n" " Options:\n" " -a : Apply boot config to initrd\n" " -d : Delete boot config file from initrd\n" " -l : list boot config in initrd or file\n\n" " If no option is given, show the bootconfig in the given file.\n"); return -1;
}
int main(int argc, char **argv)
{ char *path = NULL; char *apply = NULL; booldelete = false, list = false; int opt;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.