diff --git a/ks.c b/ks.c index f9d72d8..f3acb3d 100644 --- a/ks.c +++ b/ks.c @@ -103,7 +103,7 @@ int main(int argc, char **argv) return 1; } filename = &optarg[colon - optarg + 1]; - ret = load_sahara_image(filename, &mappings[file_id]); + ret = load_sahara_image(filename, &mappings[file_id], NULL); if (ret < 0) return 1; diff --git a/patch.c b/patch.c index 5c21c7a..23f7006 100644 --- a/patch.c +++ b/patch.c @@ -16,7 +16,7 @@ static struct list_head patches = LIST_INIT(patches); static bool patches_loaded; -int patch_load(const char *patch_file) +int patch_load(const char *patch_file, const char *incdir) { struct patch *patch; xmlNode *node; @@ -24,11 +24,16 @@ int patch_load(const char *patch_file) xmlDoc *doc; int errors; - doc = xmlReadFile(patch_file, NULL, 0); + char *patch_file_resolved = strdup(patch_file); + + resolve_path(&patch_file_resolved, incdir); + doc = xmlReadFile(patch_file_resolved, NULL, 0); if (!doc) { ux_err("failed to parse patch-type file \"%s\"\n", patch_file); + free(patch_file_resolved); return -EINVAL; } + free(patch_file_resolved); root = xmlDocGetRootElement(doc); for (node = root->children; node ; node = node->next) { diff --git a/patch.h b/patch.h index 30f5df4..d14d56f 100644 --- a/patch.h +++ b/patch.h @@ -19,7 +19,7 @@ struct patch { struct list_head node; }; -int patch_load(const char *patch_file); +int patch_load(const char *patch_file, const char *incdir); int patch_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct patch *patch)); void free_patches(void); diff --git a/program.c b/program.c index c4dcaf4..a0d6483 100644 --- a/program.c +++ b/program.c @@ -185,13 +185,7 @@ static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, con } if (program->filename) { - if (incdir) { - snprintf(tmp, PATH_MAX, "%s/%s", incdir, program->filename); - if (access(tmp, F_OK) != -1) { - free((void *)program->filename); - program->filename = strdup(tmp); - } - } + resolve_path(&program->filename, incdir); fd = open(program->filename, O_RDONLY | O_BINARY); if (fd < 0) { @@ -234,12 +228,17 @@ int program_load(const char *program_file, bool is_nand, bool allow_missing, con xmlNode *root; xmlDoc *doc; int errors = 0; + char *program_file_resolved = strdup(program_file); + + resolve_path(&program_file_resolved, incdir); - doc = xmlReadFile(program_file, NULL, 0); + doc = xmlReadFile(program_file_resolved, NULL, 0); if (!doc) { ux_err("failed to parse program-type file \"%s\"\n", program_file); + free(program_file_resolved); return -EINVAL; } + free(program_file_resolved); root = xmlDocGetRootElement(doc); for (node = root->children; node ; node = node->next) { diff --git a/program.h b/program.h index 5583d0d..65ad31e 100644 --- a/program.h +++ b/program.h @@ -11,7 +11,7 @@ struct program { unsigned int pages_per_block; unsigned int sector_size; unsigned int file_offset; - const char *filename; + char *filename; const char *label; unsigned int num_sectors; int partition; diff --git a/qdl.c b/qdl.c index 94301b9..2d1154a 100644 --- a/qdl.c +++ b/qdl.c @@ -43,7 +43,7 @@ enum { bool qdl_debug; -static int detect_type(const char *verb) +static int detect_type(const char *verb, const char *incdir) { xmlNode *root; xmlDoc *doc; @@ -57,16 +57,22 @@ static int detect_type(const char *verb) if (!strcmp(verb, "erase")) return QDL_CMD_ERASE; - if (access(verb, F_OK)) { + char *filename = strdup(verb); + resolve_path(&filename, incdir); + + if (access(filename, F_OK)) { ux_err("%s is not a verb and not a XML file\n", verb); + free(filename); return -EINVAL; } - doc = xmlReadFile(verb, NULL, 0); + doc = xmlReadFile(filename, NULL, 0); if (!doc) { ux_err("failed to parse XML file \"%s\"\n", verb); + free(filename); return -EINVAL; } + free(filename); root = xmlDocGetRootElement(doc); if (!xmlStrcmp(root->name, (xmlChar *)"patches")) { @@ -251,6 +257,7 @@ static int decode_programmer_archive(struct sahara_image *blob, struct sahara_im * decode_sahara_config() - Attempt to decode a Sahara config XML document * @blob: Loaded image to be decoded as Sahara config * @images: List of Sahara images, with @images[0] populated + * @incdir: include directory to be searched for the files specified in the Sahara config * * The single blob provided in @images[0] might be a XML blob containing * a sahara_config document with definitions of the various Sahara images that @@ -261,7 +268,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, const char *incdir) { char image_path_full[PATH_MAX]; const char *image_path; @@ -342,7 +349,7 @@ static int decode_sahara_config(struct sahara_image *blob, struct sahara_image * free((void *)image_path); - ret = load_sahara_image(image_path_full, &images[image_id]); + ret = load_sahara_image(image_path_full, &images[image_id], incdir); if (ret < 0) goto err_free_doc; } @@ -370,6 +377,7 @@ static int decode_sahara_config(struct sahara_image *blob, struct sahara_image * * decode_programmer() - decodes the programmer specifier * @s: programmer specifier, from the user * @images: array of images to populate + * @incdir: include directory to be searched for the files specified in @s * * This parses the programmer specifier @s, which can either be a single * filename, or a comma-separated series of : entries. @@ -386,7 +394,7 @@ static int decode_sahara_config(struct sahara_image *blob, struct sahara_image * * * Returns: 0 on success, -1 otherwise. */ -static int decode_programmer(char *s, struct sahara_image *images) +static int decode_programmer(char *s, struct sahara_image *images, const char *incdir) { struct sahara_image archive; char *filename; @@ -411,12 +419,12 @@ static int decode_programmer(char *s, struct sahara_image *images) } filename = &tail[1]; - ret = load_sahara_image(filename, &images[id]); + ret = load_sahara_image(filename, &images[id], incdir); if (ret < 0) return -1; } } else { - ret = load_sahara_image(s, &archive); + ret = load_sahara_image(s, &archive, incdir); if (ret < 0) return -1; @@ -424,7 +432,7 @@ static int decode_programmer(char *s, struct sahara_image *images) if (ret < 0 || ret == 1) return ret; - ret = decode_sahara_config(&archive, images); + ret = decode_sahara_config(&archive, images, incdir); if (ret < 0 || ret == 1) return ret; @@ -695,18 +703,18 @@ static int qdl_flash(int argc, char **argv) if (qdl_debug) print_version(); - ret = decode_programmer(argv[optind++], sahara_images); + ret = decode_programmer(argv[optind++], sahara_images, incdir); if (ret < 0) goto out_cleanup; do { - type = detect_type(argv[optind]); + type = detect_type(argv[optind], incdir); if (type < 0 || type == QDL_FILE_UNKNOWN) errx(1, "failed to detect file type of %s\n", argv[optind]); switch (type) { case QDL_FILE_PATCH: - ret = patch_load(argv[optind]); + ret = patch_load(argv[optind], incdir); if (ret < 0) errx(1, "patch_load %s failed", argv[optind]); break; @@ -728,7 +736,7 @@ static int qdl_flash(int argc, char **argv) if (storage_type != QDL_STORAGE_UFS) errx(1, "attempting to load provisioning config when storage isn't \"ufs\""); - ret = ufs_load(argv[optind], qdl_finalize_provisioning); + ret = ufs_load(argv[optind], qdl_finalize_provisioning, incdir); if (ret < 0) errx(1, "ufs_load %s failed", argv[optind]); break; diff --git a/qdl.h b/qdl.h index 6b51538..c1f4e3b 100644 --- a/qdl.h +++ b/qdl.h @@ -112,12 +112,13 @@ int firehose_read_buf(struct qdl_device *qdl, struct read_op *read_op, void *out int sahara_run(struct qdl_device *qdl, const struct sahara_image *images, const char *ramdump_path, const char *ramdump_filter); -int load_sahara_image(const char *filename, struct sahara_image *image); +int load_sahara_image(const char *filename, struct sahara_image *image, const char *incdir); void sahara_images_free(struct sahara_image *images, size_t count); void print_hex_dump(const char *prefix, const void *buf, size_t len); unsigned int attr_as_unsigned(xmlNode *node, const char *attr, int *errors); const char *attr_as_string(xmlNode *node, const char *attr, int *errors); bool attr_as_bool(xmlNode *node, const char *attr, int *errors); +void resolve_path(char **filename, const char *incdir); void ux_init(void); void ux_err(const char *fmt, ...); diff --git a/read.c b/read.c index 697102e..22333e1 100644 --- a/read.c +++ b/read.c @@ -27,12 +27,17 @@ int read_op_load(const char *read_op_file, const char *incdir) xmlDoc *doc; int errors; char tmp[PATH_MAX]; + char *read_op_file_resolved = strdup(read_op_file); - doc = xmlReadFile(read_op_file, NULL, 0); + resolve_path(&read_op_file_resolved, incdir); + + doc = xmlReadFile(read_op_file_resolved, NULL, 0); if (!doc) { ux_err("failed to parse read-type file \"%s\"\n", read_op_file); + free(read_op_file_resolved); return -EINVAL; } + free(read_op_file_resolved); root = xmlDocGetRootElement(doc); for (node = root->children; node ; node = node->next) { diff --git a/ufs.c b/ufs.c index b7cada4..67a9e17 100644 --- a/ufs.c +++ b/ufs.c @@ -116,7 +116,7 @@ struct ufs_epilogue *ufs_parse_epilogue(xmlNode *node) return result; } -int ufs_load(const char *ufs_file, bool finalize_provisioning) +int ufs_load(const char *ufs_file, bool finalize_provisioning, const char *incdir) { xmlNode *node; xmlNode *root; @@ -130,12 +130,17 @@ int ufs_load(const char *ufs_file, bool finalize_provisioning) ufs_file); return -EEXIST; } + char *ufs_file_resolved = strdup(ufs_file); + + resolve_path(&ufs_file_resolved, incdir); doc = xmlReadFile(ufs_file, NULL, 0); if (!doc) { ux_err("failed to parse ufs-type file \"%s\"\n", ufs_file); + free(ufs_file_resolved); return -EINVAL; } + free(ufs_file_resolved); root = xmlDocGetRootElement(doc); diff --git a/ufs.h b/ufs.h index 5c17449..ad1b3b6 100644 --- a/ufs.h +++ b/ufs.h @@ -47,7 +47,7 @@ struct ufs_epilogue { bool commit; }; -int ufs_load(const char *ufs_file, bool finalize_provisioning); +int ufs_load(const char *ufs_file, bool finalize_provisioning, const char *incdir); int ufs_provisioning_execute(struct qdl_device *qdl, int (*apply_ufs_common)(struct qdl_device *qdl, struct ufs_common *ufs), int (*apply_ufs_body)(struct qdl_device *qdl, struct ufs_body *ufs), diff --git a/util.c b/util.c index c819401..8a8dc83 100644 --- a/util.c +++ b/util.c @@ -211,26 +211,49 @@ int parse_storage_address(const char *address, int *physical_partition, return 0; } +/** + * @brief Resolves a given filename and determines if it's found in the include dir + * + * @filename: file to be found + * @incdir: include directory to be searched for the file + */ +void resolve_path(char **filename, const char *incdir) +{ + char tmp[PATH_MAX]; + if (incdir) { + snprintf(tmp, PATH_MAX, "%s/%s", incdir, *filename); + if (access(tmp, F_OK) != -1) { + free((void *)*filename); + *filename = strdup(tmp); + } + } +} + /** * load_sahara_image() - Load the content of the given file into the image * @filename: file to be loaded * @image: Sahara image object to be populated + * @incdir: include directory to be searched for the file * * Read the content of the given @filename into the given @image, update the * @image->len, and then populate the @image->name for debugging purposes. * * Returns: 0 on success, -1 on error */ -int load_sahara_image(const char *filename, struct sahara_image *image) +int load_sahara_image(const char *filename, struct sahara_image *image, const char *incdir) { ssize_t n; off_t len; void *ptr; int fd; + char *filename_resolved = strdup(filename); + + resolve_path(&filename_resolved, incdir); - fd = open(filename, O_RDONLY | O_BINARY); + fd = open(filename_resolved, O_RDONLY | O_BINARY); if (fd < 0) { ux_err("failed to read \"%s\"\n", filename); + free(filename_resolved); return -1; } @@ -254,6 +277,7 @@ int load_sahara_image(const char *filename, struct sahara_image *image) goto err_close; } + free(filename_resolved); close(fd); image->name = strdup(filename); @@ -263,6 +287,7 @@ int load_sahara_image(const char *filename, struct sahara_image *image) return 0; err_close: + free(filename_resolved); close(fd); return -1; }