diff --git a/file.c b/file.c index 4550193..9f958f3 100644 --- a/file.c +++ b/file.c @@ -183,6 +183,7 @@ int qdl_zip_open(const char *filename, struct qdl_zip **__qdl_zip) qdl_zip = calloc(1, sizeof(*qdl_zip)); if (!qdl_zip) { zip_close(zip); + *__qdl_zip = NULL; return -1; } diff --git a/flashmap.c b/flashmap.c index 54965b0..8ccb18e 100644 --- a/flashmap.c +++ b/flashmap.c @@ -26,14 +26,55 @@ static int flashmap_get_programmers(struct qdl_zip *zip, struct json_value *layo const char *filename; char path[PATH_MAX]; int count; + const char *spec; + char *tail; + unsigned long id; + int i; programmers = json_get_child(layout, "programmer"); count = json_count_children(programmers); - if (count != 1) { - ux_err("flashmap: single programmer expected, found %d\n", count); + if (count < 1) { + ux_err("flashmap: programmer list is missing or empty\n"); return -1; } + if (count > 1) { + for (i = 0; i < count; i++) { + spec = json_get_element_string(programmers, i); + if (!spec) { + ux_err("flashmap: parse error when decoding programmer\n"); + return -1; + } + + id = strtoul(spec, &tail, 0); + + if (tail == spec || *tail != ':' || tail[1] == '\0') { + ux_err("flashmap: invalid programmer entry \"%s\"\n", spec); + return -1; + } + + if (id == 0 || id >= MAPPING_SZ) { + ux_err("flashmap: invalid programmer id for \"%s\"\n", spec); + return -1; + } + + filename = tail + 1; + + if (incdir) { + snprintf(path, PATH_MAX, "%s/%s", incdir, filename); + if (access(path, F_OK)) + snprintf(path, PATH_MAX, "%s", filename); + } else { + snprintf(path, PATH_MAX, "%s", filename); + } + + if (load_sahara_image(zip, path, images + id)) + return -1; + } + + return 0; + } + filename = json_get_element_string(programmers, 0); if (!filename) { ux_err("flashmap: parse error when decoding programmer\n"); @@ -50,7 +91,7 @@ static int flashmap_get_programmers(struct qdl_zip *zip, struct json_value *layo ux_debug("flashmap: selected programmer: %s\n", path); - return load_sahara_image(zip, path, &images[SAHARA_ID_EHOSTDL_IMG]); + return load_programmers(path, images, zip); } static int flashmap_load_xml(struct list_head *ops, struct qdl_zip *zip, const char *filename, @@ -283,8 +324,10 @@ int flashmap_load(struct list_head *ops, const char *filename, struct sahara_ima layout = json_get_element_object(obj, 0); ret = flashmap_get_programmers(zip, layout, images, zip ? NULL : incdir); - if (ret) + if (ret) { + sahara_images_free(images, MAPPING_SZ); goto out_free_json; + } programmable = json_get_child(layout, "programmable"); if (!programmable) { diff --git a/qdl.c b/qdl.c index 48e4784..7e722af 100644 --- a/qdl.c +++ b/qdl.c @@ -266,7 +266,7 @@ static int decode_programmer_archive(struct sahara_image *blob, struct sahara_im * * Returns: 0 if no archive was found, 1 if archive was decoded, -1 on error */ -static int decode_sahara_config(struct sahara_image *blob, struct sahara_image *images) +static int decode_sahara_config(struct sahara_image *blob, struct sahara_image *images, struct qdl_zip *zip) { char image_path_full[PATH_MAX]; const char *image_path; @@ -294,6 +294,8 @@ static int decode_sahara_config(struct sahara_image *blob, struct sahara_image * blob_name_buf = strdup(blob->name); base_path = dirname(blob_name_buf); base_path_len = strlen(base_path); + if (base_path_len == 1 && base_path[0] == '.') + base_path_len = 0; root = xmlDocGetRootElement(doc); if (xmlStrcmp(root->name, (xmlChar *)"sahara_config")) { @@ -328,7 +330,7 @@ static int decode_sahara_config(struct sahara_image *blob, struct sahara_image * image_path_len = strlen(image_path); - if (path_is_absolute(image_path)) { + if (path_is_absolute(image_path) || base_path_len == 0) { if (image_path_len + 1 > PATH_MAX) { free((void *)image_path); goto err_free_doc; @@ -347,7 +349,7 @@ static int decode_sahara_config(struct sahara_image *blob, struct sahara_image * free((void *)image_path); - ret = load_sahara_image(NULL, image_path_full, &images[image_id]); + ret = load_sahara_image(zip, image_path_full, &images[image_id]); if (ret < 0) goto err_free_doc; } @@ -385,15 +387,12 @@ static int decode_sahara_config(struct sahara_image *blob, struct sahara_image * * second case, each comma-separated entry will be split on ':' and the given * will be assigned to the @image entry indicated by the given . * - * Memory is not allocated for the various strings, instead @s will be modified - * by the tokenizer and pointers to the individual parts will be stored in the - * @images array. - * * Returns: 0 on success, -1 otherwise. */ -static int decode_programmer(char *s, struct sahara_image *images) +int load_programmers(const char *s, struct sahara_image *images, struct qdl_zip *zip) { struct sahara_image archive; + char *copy; char *filename; char *save1; char *pair; @@ -403,35 +402,46 @@ static int decode_programmer(char *s, struct sahara_image *images) strtoul(s, &tail, 0); if (tail != s && tail[0] == ':') { - for (pair = strtok_r(s, ",", &save1); pair; pair = strtok_r(NULL, ",", &save1)) { + copy = strdup(s); + if (!copy) { + ux_err("internal error: unable to allocate memory for argument\n"); + return -1; + } + + for (pair = strtok_r(copy, ",", &save1); pair; pair = strtok_r(NULL, ",", &save1)) { id = strtoul(pair, &tail, 0); - if (tail == pair) { + if (tail == pair || *tail != ':' || tail[1] == '\0') { ux_err("invalid programmer specifier\n"); + free(copy); return -1; } if (id == 0 || id >= MAPPING_SZ) { ux_err("invalid image id \"%s\"\n", pair); + free(copy); return -1; } filename = &tail[1]; - ret = load_sahara_image(NULL, filename, &images[id]); - if (ret < 0) + ret = load_sahara_image(zip, filename, &images[id]); + if (ret < 0) { + free(copy); return -1; + } } + free(copy); } else { - ret = load_sahara_image(NULL, s, &archive); + ret = load_sahara_image(zip, s, &archive); if (ret < 0) return -1; ret = decode_programmer_archive(&archive, images); - if (ret < 0 || ret == 1) - return ret; + if (ret != 0) + return (ret == 1) ? 0 : -1; - ret = decode_sahara_config(&archive, images); - if (ret < 0 || ret == 1) - return ret; + ret = decode_sahara_config(&archive, images, zip); + if (ret != 0) + return (ret == 1) ? 0 : -1; images[SAHARA_ID_EHOSTDL_IMG] = archive; } @@ -829,7 +839,7 @@ static int qdl_flash(int argc, char **argv) * "flash" subcommand. Handling of "flash" happens in the loop below. */ if (strcmp(argv[optind], "flash")) { - ret = decode_programmer(argv[optind++], sahara_images); + ret = load_programmers(argv[optind++], sahara_images, NULL); if (ret < 0) goto out_cleanup; } diff --git a/qdl.h b/qdl.h index a692557..65a9ecf 100644 --- a/qdl.h +++ b/qdl.h @@ -107,6 +107,7 @@ struct qdl_device_desc { struct qdl_device_desc *usb_list(unsigned int *devices_found); +int load_programmers(const char *s, struct sahara_image *images, struct qdl_zip *zip); int firehose_run(struct qdl_device *qdl, struct list_head *ops); int firehose_provision(struct qdl_device *qdl, bool skip_reset); int firehose_read_buf(struct qdl_device *qdl, struct firehose_op *read_op, void *out_buf, size_t out_size);