#include <stdarg.h>
#include "dentry.h"
+#include <unistd.h>
+#include <fcntl.h>
#ifdef WITH_NTFS_3G
#include <time.h>
return WIMLIB_ERR_INVALID_IMAGE;
}
-
/* If a valid image is currently selected, it can be freed if it is not
* modified. */
if (w->current_image != WIM_NO_IMAGE) {
if (boot_idx < 0 || boot_idx > w->hdr.image_count)
return WIMLIB_ERR_INVALID_IMAGE;
w->hdr.boot_idx = boot_idx;
+
+ if (boot_idx == 0) {
+ memset(&w->hdr.boot_metadata_res_entry, 0,
+ sizeof(struct resource_entry));
+ } else {
+ memcpy(&w->hdr.boot_metadata_res_entry,
+ &w->image_metadata[
+ boot_idx - 1].metadata_lte->resource_entry,
+ sizeof(struct resource_entry));
+ }
+
return 0;
}
return w->hdr.boot_idx;
}
+/* Opens a WIM readable */
+int open_wim_readable(WIMStruct *w, const char *path)
+{
+ if (w->fp != NULL)
+ fclose(w->fp);
+ wimlib_assert(path != NULL);
+ w->fp = fopen(path, "rb");
+ if (!w->fp) {
+ ERROR_WITH_ERRNO("Failed to open `%s' for reading",
+ path);
+ return WIMLIB_ERR_OPEN;
+ }
+ return 0;
+}
+
+/* Opens a WIM writable */
+int open_wim_writable(WIMStruct *w, const char *path,
+ bool trunc, bool readable)
+{
+ const char *mode;
+ if (trunc)
+ if (readable)
+ mode = "w+b";
+ else
+ mode = "wb";
+ else
+ mode = "r+b";
+
+ DEBUG("Opening `%s' read-write", path);
+ wimlib_assert(w->out_fp == NULL);
+ wimlib_assert(path != NULL);
+ w->out_fp = fopen(path, mode);
+ if (!w->out_fp) {
+ ERROR_WITH_ERRNO("Failed to open `%s' for writing", path);
+ return WIMLIB_ERR_OPEN;
+ }
+ return 0;
+}
+
/*
* Begins the reading of a WIM file; opens the file and reads its header and
* lookup table, and optionally checks the integrity.
DEBUG("Reading the WIM file `%s'", in_wim_path);
- w->fp = fopen(in_wim_path, "rb");
-
- if (!w->fp) {
- ERROR_WITH_ERRNO("Failed to open the file `%s' for reading",
- in_wim_path);
- return WIMLIB_ERR_OPEN;
- }
+ ret = open_wim_readable(w, in_wim_path);
+ if (ret != 0)
+ goto out;
w->filename = realpath(in_wim_path, NULL);
if (!w->filename) {
- ERROR("Failed to allocate memory for WIM filename");
- return WIMLIB_ERR_NOMEM;
+ ERROR_WITH_ERRNO("Failed to resolve WIM filename");
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_close;
}
ret = read_header(w->fp, &w->hdr, open_flags);
if (ret != 0)
- return ret;
+ goto out_close;
DEBUG("Wim file contains %u images", w->hdr.image_count);
if (wimlib_get_compression_type(w) == WIM_COMPRESSION_TYPE_INVALID) {
ERROR("Invalid compression type (WIM header flags = %x)",
w->hdr.flags);
- return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
+ ret = WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
+ goto out_close;
}
-
if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) {
- int integrity_status;
ret = check_wim_integrity(w,
- open_flags & WIMLIB_OPEN_FLAG_SHOW_PROGRESS,
- &integrity_status);
- if (ret != 0)
- return ret;
- if (integrity_status == WIM_INTEGRITY_NONEXISTENT) {
+ (open_flags & WIMLIB_OPEN_FLAG_SHOW_PROGRESS) != 0);
+ if (ret == WIM_INTEGRITY_NONEXISTENT) {
WARNING("No integrity information for `%s'; skipping "
"integrity check.", w->filename);
- } else if (integrity_status == WIM_INTEGRITY_NOT_OK) {
+ } else if (ret == WIM_INTEGRITY_NOT_OK) {
ERROR("WIM is not intact! (Failed integrity check)");
- return WIMLIB_ERR_INTEGRITY;
+ ret = WIMLIB_ERR_INTEGRITY;
+ goto out_close;
+ } else if (ret != 0) {
+ goto out_close;
}
}
if (resource_is_compressed(&w->hdr.lookup_table_res_entry)) {
ERROR("Didn't expect a compressed lookup table!");
ERROR("Ask the author to implement support for this.");
- return WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE;
+ ret = WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE;
+ goto out_close;
}
ret = read_lookup_table(w);
if (ret != 0)
- return ret;
+ goto out_close;
w->image_metadata = CALLOC(w->hdr.image_count,
sizeof(struct image_metadata));
if (!w->image_metadata) {
ERROR("Failed to allocate memory for %u metadata structures",
w->hdr.image_count);
- return WIMLIB_ERR_NOMEM;
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_lookup_table;
}
w->current_image = 0;
append_metadata_resource_entry, w);
if (ret != 0)
- return ret;
+ goto out_free_image_metadata;
/* Make sure all the expected images were found. (We already have
* returned false if *extra* images were found) */
{
ERROR("Only found %u images in WIM, but expected %u",
w->current_image, w->hdr.image_count);
- return WIMLIB_ERR_IMAGE_COUNT;
+ ret = WIMLIB_ERR_IMAGE_COUNT;
+ goto out_free_image_metadata;
}
-
/* Sort images by the position of their metadata resources. I'm
* assuming that is what determines the other of the images in the WIM
* file, rather than their order in the lookup table, which is random
ret = read_xml_data(w->fp, &w->hdr.xml_res_entry,
&w->xml_data, &w->wim_info);
- if (ret != 0) {
- ERROR("Missing or invalid XML data");
- return ret;
- }
+ if (ret != 0)
+ goto out_free_image_metadata;
xml_num_images = wim_info_get_num_images(w->wim_info);
if (xml_num_images != w->hdr.image_count) {
"in the XML data,", in_wim_path, xml_num_images);
ERROR("but %u images in the WIM! There must be exactly one "
"<IMAGE> element per image.", w->hdr.image_count);
- return WIMLIB_ERR_IMAGE_COUNT;
+ ret = WIMLIB_ERR_IMAGE_COUNT;
+ goto out_free_xml_data;
}
DEBUG("Done beginning read of WIM file `%s'.", in_wim_path);
return 0;
+
+ //
+ // Everything is freed in wimlib_free() anyway, so no need to roll back
+ // changes here.
+ //
+out_free_xml_data:
+ /*FREE(w->xml_data);*/
+ /*w->xml_data = NULL;*/
+ /*free_wim_info(w->wim_info);*/
+ /*w->wim_info = NULL;*/
+out_free_image_metadata:
+ /*FREE(w->image_metadata);*/
+ /*w->image_metadata = NULL;*/
+ /*w->current_image = WIM_NO_IMAGE;*/
+out_free_lookup_table:
+ /*free_lookup_table(w->lookup_table);*/
+ /*w->lookup_table = NULL;*/
+out_close:
+ /*fclose(w->fp);*/
+ /*w->fp = NULL;*/
+out:
+ return ret;
}
#endif
FREE(w);
}
-