X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fxml.c;h=9a0bded26bbfc4f863c9db2ecf820e8a794d5d7f;hp=ff7925204017f869fca3b9f5a5169fd80c6b5951;hb=a523981c40a013fc5d5ca382e4cacb46667934e3;hpb=5046b052366414f09940041ad79244c320d24751 diff --git a/src/xml.c b/src/xml.c index ff792520..9a0bded2 100644 --- a/src/xml.c +++ b/src/xml.c @@ -209,10 +209,13 @@ static void destroy_windows_info(struct windows_info *windows_info) FREE(windows_info->product_name); FREE(windows_info->edition_id); FREE(windows_info->installation_type); + FREE(windows_info->hal); FREE(windows_info->product_type); + FREE(windows_info->product_suite); for (i = 0; i < windows_info->num_languages; i++) FREE(windows_info->languages[i]); FREE(windows_info->languages); + FREE(windows_info->default_language); FREE(windows_info->system_root); } @@ -243,7 +246,7 @@ void free_wim_info(struct wim_info *info) /* Reads the information from a element inside the element. * */ -static void xml_read_windows_version(const xmlNode *version_node, +static void xml_read_windows_version(const xmlNode *version_node, struct windows_version* windows_version) { xmlNode *child; @@ -265,8 +268,8 @@ static void xml_read_windows_version(const xmlNode *version_node, /* Reads the information from a element inside a element. * */ -static int xml_read_languages(const xmlNode *languages_node, - char ***languages_ret, +static int xml_read_languages(const xmlNode *languages_node, + char ***languages_ret, u64 *num_languages_ret, char **default_language_ret) { @@ -306,7 +309,7 @@ static int xml_read_languages(const xmlNode *languages_node, } /* Reads the information from a element inside an element. */ -static int xml_read_windows_info(const xmlNode *windows_node, +static int xml_read_windows_info(const xmlNode *windows_node, struct windows_info *windows_info) { xmlNode *child; @@ -318,27 +321,27 @@ static int xml_read_windows_info(const xmlNode *windows_node, if (node_name_is(child, "ARCH")) { windows_info->arch = node_get_u64(child); } else if (node_name_is(child, "PRODUCTNAME")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->product_name); } else if (node_name_is(child, "EDITIONID")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->edition_id); } else if (node_name_is(child, "INSTALLATIONTYPE")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->installation_type); } else if (node_name_is(child, "PRODUCTTYPE")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->product_type); } else if (node_name_is(child, "PRODUCTSUITE")) { - ret = node_get_string(child, + ret = node_get_string(child, &windows_info->product_suite); } else if (node_name_is(child, "LANGUAGES")) { - ret = xml_read_languages(child, + ret = xml_read_languages(child, &windows_info->languages, &windows_info->num_languages, &windows_info->default_language); } else if (node_name_is(child, "VERSION")) { - xml_read_windows_version(child, + xml_read_windows_version(child, &windows_info->windows_version); windows_info->windows_version_exists = true; } else if (node_name_is(child, "SYSTEMROOT")) { @@ -354,13 +357,13 @@ static int xml_read_windows_info(const xmlNode *windows_node, } /* Reads the information from an element. */ -static int xml_read_image_info(xmlNode *image_node, +static int xml_read_image_info(xmlNode *image_node, struct image_info *image_info) { xmlNode *child; xmlChar *index_prop; int ret; - + index_prop = xmlGetProp(image_node, "INDEX"); if (index_prop) { char *tmp; @@ -467,7 +470,7 @@ static int xml_read_wim_info(const xmlNode *wim_node, } /* Sort the array of struct image_infos by image index. */ - qsort(wim_info->images, wim_info->num_images, + qsort(wim_info->images, wim_info->num_images, sizeof(struct image_info), sort_by_index); done: *wim_info_ret = wim_info; @@ -484,33 +487,52 @@ static void print_windows_info(const struct windows_info *windows_info) const struct windows_version *windows_version; printf("Architecture: %s\n", get_arch(windows_info->arch)); - printf("Product Name: %s\n", windows_info->product_name); - printf("Edition ID: %s\n", windows_info->edition_id); - printf("Installation Type: %s\n", windows_info->installation_type); + + if (windows_info->product_name) + printf("Product Name: %s\n", + windows_info->product_name); + + if (windows_info->edition_id) + printf("Edition ID: %s\n", + windows_info->edition_id); + + if (windows_info->installation_type) + printf("Installation Type: %s\n", + windows_info->installation_type); + if (windows_info->hal) printf("HAL: %s\n", windows_info->hal); - printf("Product Type: %s\n", windows_info->product_type); + + if (windows_info->product_type) + printf("Product Type: %s\n", + windows_info->product_type); + if (windows_info->product_suite) - printf("Product Suite: %s\n", windows_info->product_suite); + printf("Product Suite: %s\n", + windows_info->product_suite); printf("Languages: "); for (i = 0; i < windows_info->num_languages; i++) { fputs(windows_info->languages[i], stdout); putchar(' '); } putchar('\n'); - printf("Default Language: %s\n", windows_info->default_language); - printf("System Root: %s\n", windows_info->system_root); + if (windows_info->default_language) + printf("Default Language: %s\n", + windows_info->default_language); + if (windows_info->system_root) + printf("System Root: %s\n", + windows_info->system_root); if (windows_info->windows_version_exists) { windows_version = &windows_info->windows_version; - printf("Major Version: %"PRIu64"\n", + printf("Major Version: %"PRIu64"\n", windows_version->major); - printf("Minor Version: %"PRIu64"\n", + printf("Minor Version: %"PRIu64"\n", windows_version->minor); - printf("Build: %"PRIu64"\n", + printf("Build: %"PRIu64"\n", windows_version->build); - printf("Service Pack Build: %"PRIu64"\n", + printf("Service Pack Build: %"PRIu64"\n", windows_version->sp_build); - printf("Service Pack Level: %"PRIu64"\n", + printf("Service Pack Level: %"PRIu64"\n", windows_version->sp_level); } } @@ -519,35 +541,35 @@ static void print_windows_info(const struct windows_info *windows_info) /* Writes the information contained in a struct windows_version structure to the XML * document being constructed in memory. This is the element inside * the element. */ -static int xml_write_windows_version(xmlTextWriter *writer, - const struct windows_version *version) +static int xml_write_windows_version(xmlTextWriter *writer, + const struct windows_version *version) { int rc; rc = xmlTextWriterStartElement(writer, "VERSION"); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "MAJOR", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "MAJOR", "%"PRIu64, version->major); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "MINOR", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "MINOR", "%"PRIu64, version->minor); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "BUILD", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "BUILD", "%"PRIu64, version->build); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "SPBUILD", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "SPBUILD", "%"PRIu64, version->sp_build); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "SPLEVEL", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "SPLEVEL", "%"PRIu64, version->sp_level); if (rc < 0) return rc; @@ -557,8 +579,8 @@ static int xml_write_windows_version(xmlTextWriter *writer, /* Writes the information contained in a struct windows_info structure to the XML * document being constructed in memory. This is the element. */ -static int xml_write_windows_info(xmlTextWriter *writer, - const struct windows_info *windows_info) +static int xml_write_windows_info(xmlTextWriter *writer, + const struct windows_info *windows_info) { int rc; rc = xmlTextWriterStartElement(writer, "WINDOWS"); @@ -566,55 +588,48 @@ static int xml_write_windows_info(xmlTextWriter *writer, return rc; - rc = xmlTextWriterWriteFormatElement(writer, "ARCH", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "ARCH", "%"PRIu64, windows_info->arch); if (rc < 0) return rc; - + if (windows_info->product_name) { - rc = xmlTextWriterWriteElement(writer, "PRODUCTNAME", + rc = xmlTextWriterWriteElement(writer, "PRODUCTNAME", windows_info->product_name); if (rc < 0) return rc; } if (windows_info->edition_id) { - rc = xmlTextWriterWriteElement(writer, "EDITIONID", + rc = xmlTextWriterWriteElement(writer, "EDITIONID", windows_info->edition_id); if (rc < 0) return rc; } if (windows_info->installation_type) { - rc = xmlTextWriterWriteElement(writer, "INSTALLATIONTYPE", + rc = xmlTextWriterWriteElement(writer, "INSTALLATIONTYPE", windows_info->installation_type); if (rc < 0) return rc; } if (windows_info->hal) { - rc = xmlTextWriterWriteElement(writer, "HAL", + rc = xmlTextWriterWriteElement(writer, "HAL", windows_info->hal); if (rc < 0) return rc; } - if (windows_info->system_root) { - rc = xmlTextWriterWriteElement(writer, "SYSTEMROOT", - windows_info->system_root); - if (rc < 0) - return rc; - } - if (windows_info->product_type) { - rc = xmlTextWriterWriteElement(writer, "PRODUCTTYPE", + rc = xmlTextWriterWriteElement(writer, "PRODUCTTYPE", windows_info->product_type); if (rc < 0) return rc; } if (windows_info->product_suite) { - rc = xmlTextWriterWriteElement(writer, "PRODUCTSUITE", + rc = xmlTextWriterWriteElement(writer, "PRODUCTSUITE", windows_info->product_suite); if (rc < 0) return rc; @@ -626,12 +641,12 @@ static int xml_write_windows_info(xmlTextWriter *writer, return rc; for (int i = 0; i < windows_info->num_languages; i++) { - rc = xmlTextWriterWriteElement(writer, "LANGUAGE", + rc = xmlTextWriterWriteElement(writer, "LANGUAGE", windows_info->languages[i]); if (rc < 0) return rc; } - rc = xmlTextWriterWriteElement(writer, "DEFAULT", + rc = xmlTextWriterWriteElement(writer, "DEFAULT", windows_info->default_language); if (rc < 0) return rc; @@ -647,25 +662,32 @@ static int xml_write_windows_info(xmlTextWriter *writer, return rc; } + if (windows_info->system_root) { + rc = xmlTextWriterWriteElement(writer, "SYSTEMROOT", + windows_info->system_root); + if (rc < 0) + return rc; + } + return xmlTextWriterEndElement(writer); /* */ } /* Writes a time element to the XML document being constructed in memory. */ -static int xml_write_time(xmlTextWriter *writer, const char *element_name, - u64 time) +static int xml_write_time(xmlTextWriter *writer, const char *element_name, + u64 time) { int rc; rc = xmlTextWriterStartElement(writer, element_name); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "HIGHPART", - "0x%"PRIX32, (u32)(time >> 32)); + rc = xmlTextWriterWriteFormatElement(writer, "HIGHPART", + "0x%08"PRIX32, (u32)(time >> 32)); if (rc < 0) return rc; rc = xmlTextWriterWriteFormatElement(writer, "LOWPART", - "0x%"PRIX32, (u32)time); + "0x%08"PRIX32, (u32)time); if (rc < 0) return rc; @@ -677,7 +699,7 @@ static int xml_write_time(xmlTextWriter *writer, const char *element_name, /* Writes an element to the XML document. */ -static int xml_write_image_info(xmlTextWriter *writer, +static int xml_write_image_info(xmlTextWriter *writer, const struct image_info *image_info) { int rc; @@ -685,37 +707,37 @@ static int xml_write_image_info(xmlTextWriter *writer, if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatAttribute(writer, "INDEX", "%"PRIu64, + rc = xmlTextWriterWriteFormatAttribute(writer, "INDEX", "%"PRIu64, image_info->index); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "DIRCOUNT", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "DIRCOUNT", "%"PRIu64, image_info->dir_count); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "FILECOUNT", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "FILECOUNT", "%"PRIu64, image_info->file_count); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "TOTALBYTES", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "TOTALBYTES", "%"PRIu64, image_info->total_bytes); if (rc < 0) return rc; - rc = xmlTextWriterWriteFormatElement(writer, "HARDLINKBYTES", "%"PRIu64, + rc = xmlTextWriterWriteFormatElement(writer, "HARDLINKBYTES", "%"PRIu64, image_info->hard_link_bytes); if (rc < 0) return rc; - rc = xml_write_time(writer, "CREATIONTIME", + rc = xml_write_time(writer, "CREATIONTIME", image_info->creation_time); if (rc < 0) return rc; - rc = xml_write_time(writer, "LASTMODIFICATIONTIME", + rc = xml_write_time(writer, "LASTMODIFICATIONTIME", image_info->last_modification_time); if (rc < 0) return rc; @@ -734,19 +756,19 @@ static int xml_write_image_info(xmlTextWriter *writer, return rc; } if (image_info->description) { - rc = xmlTextWriterWriteElement(writer, "DESCRIPTION", + rc = xmlTextWriterWriteElement(writer, "DESCRIPTION", image_info->description); if (rc < 0) return rc; } if (image_info->display_name) { - rc = xmlTextWriterWriteElement(writer, "DISPLAYNAME", + rc = xmlTextWriterWriteElement(writer, "DISPLAYNAME", image_info->display_name); if (rc < 0) return rc; } if (image_info->display_description) { - rc = xmlTextWriterWriteElement(writer, "DISPLAYDESCRIPTION", + rc = xmlTextWriterWriteElement(writer, "DISPLAYDESCRIPTION", image_info->display_description); if (rc < 0) return rc; @@ -781,7 +803,7 @@ static struct image_info *add_image_info_struct(struct wim_info *wim_info) return &images[wim_info->num_images - 1]; } -static int clone_windows_info(const struct windows_info *old, +static int clone_windows_info(const struct windows_info *old, struct windows_info *new) { uint i; @@ -790,7 +812,7 @@ static int clone_windows_info(const struct windows_info *old, return WIMLIB_ERR_NOMEM; if (old->edition_id && !(new->edition_id = STRDUP(old->edition_id))) return WIMLIB_ERR_NOMEM; - if (old->installation_type && !(new->installation_type = + if (old->installation_type && !(new->installation_type = STRDUP(old->installation_type))) return WIMLIB_ERR_NOMEM; if (old->hal && !(new->hal = STRDUP(old->hal))) @@ -813,7 +835,7 @@ static int clone_windows_info(const struct windows_info *old, return WIMLIB_ERR_NOMEM; } } - if (old->default_language && + if (old->default_language && !(new->default_language = STRDUP(old->default_language))) return WIMLIB_ERR_NOMEM; if (old->system_root && !(new->system_root = STRDUP(old->system_root))) @@ -856,13 +878,13 @@ static int clone_image_info(const struct image_info *old, struct image_info *new if (old->windows_info_exists) { new->windows_info_exists = true; - return clone_windows_info(&old->windows_info, + return clone_windows_info(&old->windows_info, &new->windows_info); } return 0; } -/* Copies the XML information for an image between WIM files. +/* Copies the XML information for an image between WIM files. * * @dest_image_name and @dest_image_description are ignored if they are NULL; * otherwise, they are used to override the image name and/or image description @@ -871,10 +893,10 @@ static int clone_image_info(const struct image_info *old, struct image_info *new * On failure, WIMLIB_ERR_NOMEM is returned and no changes are made. Otherwise, * 0 is returned and the WIM information at *new_wim_info_p is modified. */ -int xml_export_image(const struct wim_info *old_wim_info, - int image, - struct wim_info **new_wim_info_p, - const char *dest_image_name, +int xml_export_image(const struct wim_info *old_wim_info, + int image, + struct wim_info **new_wim_info_p, + const char *dest_image_name, const char *dest_image_description) { struct wim_info *new_wim_info; @@ -930,7 +952,7 @@ void xml_delete_image(struct wim_info **wim_info_p, int image) int i; DEBUG("Deleting image %d from the XML data.", image); - + wim_info = *wim_info_p; wimlib_assert(wim_info); @@ -971,7 +993,7 @@ void xml_set_memory_allocator(void *(*malloc_func)(size_t), static int calculate_dentry_statistics(struct dentry *dentry, void *arg) { - struct image_info *info = arg; + struct image_info *info = arg; struct lookup_table *lookup_table = info->lookup_table; const struct inode *inode = dentry->d_inode; struct lookup_table_entry *lte; @@ -979,7 +1001,7 @@ static int calculate_dentry_statistics(struct dentry *dentry, void *arg) /* Update directory count and file count. * * Each dentry counts as either a file or a directory, but not both. - * The root directory is an exception: it is not counted. + * The root directory is an exception: it is not counted at all. * * Symbolic links and junction points (and presumably other reparse * points) count as regular files. This is despite the fact that @@ -993,7 +1015,7 @@ static int calculate_dentry_statistics(struct dentry *dentry, void *arg) else info->file_count++; - /* + /* * Update total bytes and hard link bytes. * * Unfortunately there are some inconsistencies/bugs in the way this is @@ -1043,7 +1065,6 @@ static int calculate_dentry_statistics(struct dentry *dentry, void *arg) void xml_update_image_info(WIMStruct *w, int image) { struct image_info *image_info; - struct dentry *root; char *flags_save; DEBUG("Updating the image info for image %d", image); @@ -1061,7 +1082,7 @@ void xml_update_image_info(WIMStruct *w, int image) for_dentry_in_tree(w->image_metadata[image - 1].root_dentry, calculate_dentry_statistics, image_info); - + image_info->lookup_table = NULL; image_info->flags = flags_save; image_info->last_modification_time = get_wim_timestamp(); @@ -1106,94 +1127,81 @@ int xml_add_image(WIMStruct *w, const char *name) out_destroy_image_info: destroy_image_info(image_info); + wim_info->num_images--; out_free_wim_info: - if (w->wim_info) - wim_info->num_images--; - else + if (wim_info != w->wim_info) FREE(wim_info); ERROR("Out of memory"); return WIMLIB_ERR_NOMEM; } -/* Prints information about the specified image from struct wim_info structure. - * @image may be WIM_ALL_IMAGES. */ +/* Prints information about the specified image from struct wim_info structure. + * */ void print_image_info(const struct wim_info *wim_info, int image) { - uint i; const struct image_info *image_info; const char *desc; + time_t time; + char *p; + wimlib_assert(image >= 1 && image <= wim_info->num_images); - if (image == WIM_ALL_IMAGES) { - for (i = 1; i <= wim_info->num_images; i++) - print_image_info(wim_info, i); - } else { - time_t time; - char *p; + image_info = &wim_info->images[image - 1]; - image_info = &wim_info->images[image - 1]; + printf("Index: %"PRIu64"\n", image_info->index); + printf("Name: %s\n", image_info->name); - printf("Index: %"PRIu64"\n", - image_info->index); - printf("Name: %s\n", - image_info->name); - - /* Always print the Description: part even if there is no - * description. */ - if (image_info->description) - desc = image_info->description; - else - desc = ""; - printf("Description: %s\n", desc); - - if (image_info->display_name) - printf("Display Name: %s\n", - image_info->display_name); - - if (image_info->display_description) - printf("Display Description: %s\n", - image_info->display_description); - - printf("Directory Count: %"PRIu64"\n", - image_info->dir_count); - printf("File Count: %"PRIu64"\n", - image_info->file_count); - printf("Total Bytes: %"PRIu64"\n", - image_info->total_bytes); - printf("Hard Link Bytes: %"PRIu64"\n", - image_info->hard_link_bytes); - - time = wim_timestamp_to_unix(image_info->creation_time); - p = asctime(gmtime(&time)); - *(strrchr(p, '\n')) = '\0'; - - printf("Creation Time: %s UTC\n", p); - - time = wim_timestamp_to_unix(image_info->last_modification_time); - p = asctime(gmtime(&time)); - *(strrchr(p, '\n')) = '\0'; - - printf("Last Modification Time: %s UTC\n", p); - if (image_info->windows_info_exists) - print_windows_info(&image_info->windows_info); - if (image_info->flags) - printf("Flags: %s\n", image_info->flags); - putchar('\n'); - } + /* Always print the Description: part even if there is no + * description. */ + if (image_info->description) + desc = image_info->description; + else + desc = ""; + printf("Description: %s\n", desc); + + if (image_info->display_name) + printf("Display Name: %s\n", + image_info->display_name); + + if (image_info->display_description) + printf("Display Description: %s\n", + image_info->display_description); + + printf("Directory Count: %"PRIu64"\n", image_info->dir_count); + printf("File Count: %"PRIu64"\n", image_info->file_count); + printf("Total Bytes: %"PRIu64"\n", image_info->total_bytes); + printf("Hard Link Bytes: %"PRIu64"\n", image_info->hard_link_bytes); + + time = wim_timestamp_to_unix(image_info->creation_time); + p = asctime(gmtime(&time)); + *(strrchr(p, '\n')) = '\0'; + + printf("Creation Time: %s UTC\n", p); + + time = wim_timestamp_to_unix(image_info->last_modification_time); + p = asctime(gmtime(&time)); + *(strrchr(p, '\n')) = '\0'; + + printf("Last Modification Time: %s UTC\n", p); + if (image_info->windows_info_exists) + print_windows_info(&image_info->windows_info); + if (image_info->flags) + printf("Flags: %s\n", image_info->flags); + putchar('\n'); } -/* +/* * Reads the XML data from a WIM file. */ -int read_xml_data(FILE *fp, const struct resource_entry *res, u8 **xml_data_ret, - struct wim_info **info_ret) +int read_xml_data(FILE *fp, const struct resource_entry *res, + u8 **xml_data_ret, struct wim_info **info_ret) { u8 *xml_data; xmlDoc *doc; xmlNode *root; int ret; - DEBUG("XML data is %"PRIu64" bytes at offset %"PRIu64"", + DEBUG("XML data is %"PRIu64" bytes at offset %"PRIu64"", (u64)res->size, res->offset); if (resource_is_compressed(res)) { @@ -1268,34 +1276,37 @@ out_cleanup_parser: #define CHECK_RET ({ if (ret < 0) { \ ERROR("Error writing XML data"); \ ret = WIMLIB_ERR_WRITE; \ - goto err2; \ + goto out_free_text_writer; \ } }) -/* +/* * Writes XML data to a WIM file. * * If @total_bytes is non-zero, it specifies what to write to the TOTALBYTES * element in the XML data. If zero, TOTALBYTES is given the default value of * the offset of the XML data. */ -int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, - u64 total_bytes) +int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, + u64 total_bytes, struct resource_entry *out_res_entry) { xmlBuffer *buf; xmlTextWriter *writer; char *utf16_str; int ret; - int num_images; - int i; const xmlChar *content; size_t len; size_t utf16_len; size_t bytes_written; + off_t start_offset, end_offset; - wimlib_assert(image == WIM_ALL_IMAGES || - (wim_info != NULL && image >= 1 && + wimlib_assert(image == WIMLIB_ALL_IMAGES || + (wim_info != NULL && image >= 1 && image <= wim_info->num_images)); + start_offset = ftello(out); + if (start_offset == -1) + return WIMLIB_ERR_WRITE; + /* The contents of the element in the XML data, under the * element not the element, is (for non-spit WIMs) the * size of the WIM file excluding the XML data and integrity table, @@ -1312,13 +1323,13 @@ int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, if (!buf) { ERROR("Failed to allocate XML buffer"); ret = WIMLIB_ERR_NOMEM; - goto err0; + goto out; } writer = xmlNewTextWriterMemory(buf, 0); if (!writer) { ERROR("Failed to allocate XML writer"); ret = WIMLIB_ERR_NOMEM; - goto err1; + goto out_buffer_free; } /* XXX */ @@ -1339,18 +1350,15 @@ int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, total_bytes); CHECK_RET; - if (wim_info) - num_images = wim_info->num_images; - else - num_images = 0; - DEBUG("Writing %u elements", num_images); - - for (i = 1; i <= num_images; i++) { - if (image != WIM_ALL_IMAGES && i != image) - continue; - DEBUG("Writing element for image %d", i); - ret = xml_write_image_info(writer, &wim_info->images[i - 1]); - CHECK_RET; + if (wim_info != NULL) { + DEBUG("Writing %d elements", (int)wim_info->num_images); + for (int i = 1; i <= (int)wim_info->num_images; i++) { + if (image != WIMLIB_ALL_IMAGES && i != image) + continue; + DEBUG("Writing element for image %d", i); + ret = xml_write_image_info(writer, &wim_info->images[i - 1]); + CHECK_RET; + } } ret = xmlTextWriterEndElement(writer); @@ -1359,36 +1367,52 @@ int write_xml_data(const struct wim_info *wim_info, int image, FILE *out, ret = xmlTextWriterEndDocument(writer); CHECK_RET; + xmlFreeTextWriter(writer); + writer = NULL; DEBUG("Done composing XML document. Now converting to UTF-16 and " "writing it to the output file."); content = xmlBufferContent(buf); len = xmlBufferLength(buf); + DEBUG("XML UTF-8 length = %zu", len); + utf16_str = utf8_to_utf16(content, len, &utf16_len); if (!utf16_str) { ret = WIMLIB_ERR_NOMEM; - goto err2; + goto out_free_text_writer; } - if ((putc(0xff, out)) == EOF || (putc(0xfe, out) == EOF) || + DEBUG("XML UTF-16 length = %zu", utf16_len); + + if ((putc(0xff, out)) == EOF || (putc(0xfe, out) == EOF) || ((bytes_written = fwrite(utf16_str, 1, utf16_len, out)) != utf16_len)) { ERROR_WITH_ERRNO("Error writing XML data"); ret = WIMLIB_ERR_WRITE; - goto err3; + goto out_free_utf16_str; } DEBUG("Cleaning up."); + end_offset = ftello(out); + if (end_offset == -1) { + ret = WIMLIB_ERR_WRITE; + goto out_free_utf16_str; + } + + out_res_entry->offset = start_offset; + out_res_entry->size = end_offset - start_offset; + out_res_entry->original_size = end_offset - start_offset; + out_res_entry->flags = WIM_RESHDR_FLAG_METADATA; ret = 0; -err3: +out_free_utf16_str: FREE(utf16_str); -err2: +out_free_text_writer: xmlFreeTextWriter(writer); -err1: +out_buffer_free: xmlBufferFree(buf); -err0: +out: return ret; } @@ -1403,7 +1427,7 @@ WIMLIBAPI const char *wimlib_get_image_name(const WIMStruct *w, int image) } /* Returns the description of the specified image. */ -WIMLIBAPI const char *wimlib_get_image_description(const WIMStruct *w, +WIMLIBAPI const char *wimlib_get_image_description(const WIMStruct *w, int image) { DEBUG("Getting the description of image %d", image); @@ -1419,7 +1443,7 @@ WIMLIBAPI bool wimlib_image_name_in_use(const WIMStruct *w, const char *name) int i; DEBUG("Checking to see if the image name `%s' is already in use", name); - if (!name || !w->wim_info) + if (!name || !*name || !w->wim_info) return false; for (i = 1; i <= w->wim_info->num_images; i++) if (strcmp(w->wim_info->images[i - 1].name, name) == 0) @@ -1431,7 +1455,10 @@ WIMLIBAPI bool wimlib_image_name_in_use(const WIMStruct *w, const char *name) WIMLIBAPI int wimlib_extract_xml_data(WIMStruct *w, FILE *fp) { DEBUG("Extracting the XML data."); - if (fwrite(w->xml_data, 1, w->hdr.xml_res_entry.size, fp) != + if (!w->xml_data) + return WIMLIB_ERR_INVALID_PARAM; + + if (fwrite(w->xml_data, 1, w->hdr.xml_res_entry.size, fp) != w->hdr.xml_res_entry.size) { ERROR_WITH_ERRNO("Failed to extract XML data"); return WIMLIB_ERR_WRITE; @@ -1480,7 +1507,7 @@ WIMLIBAPI int wimlib_set_image_name(WIMStruct *w, int image, const char *name) } /* Sets the description of an image in the WIM. */ -WIMLIBAPI int wimlib_set_image_descripton(WIMStruct *w, int image, +WIMLIBAPI int wimlib_set_image_descripton(WIMStruct *w, int image, const char *description) { char *p;