#include <limits.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <errno.h>
#include "dentry.h"
+#include <unistd.h>
+#include <fcntl.h>
#ifdef WITH_NTFS_3G
#include <time.h>
#include "lookup_table.h"
#include "xml.h"
-
static int print_metadata(WIMStruct *w)
{
DEBUG("Printing metadata for image %d", w->current_image);
WIMStruct *new_wim_struct()
{
WIMStruct *w = CALLOC(1, sizeof(WIMStruct));
+#ifdef WITH_FUSE
if (pthread_mutex_init(&w->fp_tab_mutex, NULL) != 0) {
ERROR_WITH_ERRNO("Failed to initialize mutex");
FREE(w);
w = NULL;
}
+#endif
return w;
}
/*
- * Calls a function on images in the WIM. If @image is WIM_ALL_IMAGES, @visitor
+ * Calls a function on images in the WIM. If @image is WIMLIB_ALL_IMAGES, @visitor
* is called on the WIM once for each image, with each image selected as the
* current image in turn. If @image is a certain image, @visitor is called on
* the WIM only once, with that image selected.
int end;
int i;
- if (image == WIM_ALL_IMAGES) {
+ if (image == WIMLIB_ALL_IMAGES) {
start = 1;
end = w->hdr.image_count;
} else if (image >= 1 && image <= w->hdr.image_count) {
if (lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) {
if (w->current_image == w->hdr.image_count) {
- ERROR("Expected only %u images, but found more",
+ ERROR("The WIM header says there are %u images in the WIM,\n"
+ " but we found more metadata resources than this",
w->hdr.image_count);
ret = WIMLIB_ERR_IMAGE_COUNT;
} else {
{
if (wim_hdr_flags & WIM_HDR_FLAG_COMPRESSION) {
if (wim_hdr_flags & WIM_HDR_FLAG_COMPRESS_LZX)
- return WIM_COMPRESSION_TYPE_LZX;
+ return WIMLIB_COMPRESSION_TYPE_LZX;
else if (wim_hdr_flags & WIM_HDR_FLAG_COMPRESS_XPRESS)
- return WIM_COMPRESSION_TYPE_XPRESS;
+ return WIMLIB_COMPRESSION_TYPE_XPRESS;
else
- return WIM_COMPRESSION_TYPE_INVALID;
+ return WIMLIB_COMPRESSION_TYPE_INVALID;
} else {
- return WIM_COMPRESSION_TYPE_NONE;
+ return WIMLIB_COMPRESSION_TYPE_NONE;
}
}
DEBUG("Selecting image %d", image);
+ if (image == WIMLIB_NO_IMAGE) {
+ ERROR("Invalid image: %d", WIMLIB_NO_IMAGE);
+ return WIMLIB_ERR_INVALID_IMAGE;
+ }
+
if (image == w->current_image)
return 0;
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 (w->current_image != WIMLIB_NO_IMAGE) {
imd = wim_get_current_image_metadata(w);
if (!imd->modified) {
DEBUG("Freeing image %u", w->current_image);
destroy_image_metadata(imd, NULL);
imd->root_dentry = NULL;
imd->security_data = NULL;
+ INIT_HLIST_HEAD(&imd->inode_list);
}
}
WIMLIBAPI const char *wimlib_get_compression_type_string(int ctype)
{
switch (ctype) {
- case WIM_COMPRESSION_TYPE_NONE:
+ case WIMLIB_COMPRESSION_TYPE_NONE:
return "None";
- case WIM_COMPRESSION_TYPE_LZX:
+ case WIMLIB_COMPRESSION_TYPE_LZX:
return "LZX";
- case WIM_COMPRESSION_TYPE_XPRESS:
+ case WIMLIB_COMPRESSION_TYPE_XPRESS:
return "XPRESS";
default:
return "Invalid";
int image;
int i;
- if (!image_name_or_num)
- return WIM_NO_IMAGE;
+ if (!image_name_or_num || !*image_name_or_num)
+ return WIMLIB_NO_IMAGE;
if (strcmp(image_name_or_num, "all") == 0
|| strcmp(image_name_or_num, "*") == 0)
- return WIM_ALL_IMAGES;
+ return WIMLIB_ALL_IMAGES;
image = strtol(image_name_or_num, &p, 10);
- if (p != image_name_or_num && *p == '\0') {
- if (image < 1 || image > w->hdr.image_count)
- return WIM_NO_IMAGE;
+ if (p != image_name_or_num && *p == '\0' && image > 0) {
+ if (image > w->hdr.image_count)
+ return WIMLIB_NO_IMAGE;
return image;
} else {
for (i = 1; i <= w->hdr.image_count; i++) {
wimlib_get_image_name(w, i)) == 0)
return i;
}
- return WIM_NO_IMAGE;
+ return WIMLIB_NO_IMAGE;
}
}
int last;
int i;
int n;
- if (image == WIM_ALL_IMAGES) {
+ if (image == WIMLIB_ALL_IMAGES) {
n = printf("Available Images:\n");
first = 1;
last = w->hdr.image_count;
}
-/* Prints the metadata for the specified image, which may be WIM_ALL_IMAGES, but
- * not WIM_NO_IMAGE. */
+/* Prints the metadata for the specified image, which may be WIMLIB_ALL_IMAGES, but
+ * not WIMLIB_NO_IMAGE. */
WIMLIBAPI int wimlib_print_metadata(WIMStruct *w, int image)
{
if (!w)
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;
}
* Begins the reading of a WIM file; opens the file and reads its header and
* lookup table, and optionally checks the integrity.
*/
-static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
+static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags,
+ wimlib_progress_func_t progress_func)
{
int ret;
- uint xml_num_images;
+ int xml_num_images;
DEBUG("Reading the WIM file `%s'", in_wim_path);
- w->filename = realpath(in_wim_path, NULL);
- if (!w->filename) {
- ERROR("Failed to allocate memory for WIM filename");
- return WIMLIB_ERR_NOMEM;
- }
-
w->fp = fopen(in_wim_path, "rb");
-
if (!w->fp) {
- ERROR_WITH_ERRNO("Failed to open the file `%s' for reading",
+ ERROR_WITH_ERRNO("Failed to open `%s' for reading",
in_wim_path);
return WIMLIB_ERR_OPEN;
}
+ /* The absolute path to the WIM is requested so that wimlib_overwrite()
+ * still works even if the process changes its working directory. This
+ * actually happens if a WIM is mounted read-write, since the FUSE
+ * thread changes directory to "/", and it needs to be able to find the
+ * WIM file again.
+ *
+ * This will break if the full path to the WIM changes in the
+ * intervening time...
+ */
+ w->filename = realpath(in_wim_path, NULL);
+ if (!w->filename) {
+ ERROR_WITH_ERRNO("Failed to resolve WIM filename");
+ if (errno == ENOMEM)
+ ret = WIMLIB_ERR_NOMEM;
+ else
+ ret = WIMLIB_ERR_OPEN;
+ 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);
+ DEBUG("According to header, WIM contains %u images", w->hdr.image_count);
/* If the boot index is invalid, print a warning and set it to 0 */
if (w->hdr.boot_idx > w->hdr.image_count) {
w->hdr.boot_idx = 0;
}
- if (wimlib_get_compression_type(w) == WIM_COMPRESSION_TYPE_INVALID) {
+ if (wimlib_get_compression_type(w) == WIMLIB_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) {
+ ret = check_wim_integrity(w, progress_func);
+ 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
qsort(w->image_metadata, w->current_image,
sizeof(struct image_metadata), sort_image_metadata_by_position);
- w->current_image = WIM_NO_IMAGE;
+ w->current_image = WIMLIB_NO_IMAGE;
/* Read the XML data. */
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;
+ /*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 = WIMLIB_NO_IMAGE;*/
+out_free_lookup_table:
+ /*free_lookup_table(w->lookup_table);*/
+ /*w->lookup_table = NULL;*/
+out_close:
+ /*fclose(w->fp);*/
+ /*w->fp = NULL;*/
+ return ret;
}
* Opens a WIM file and creates a WIMStruct for it.
*/
WIMLIBAPI int wimlib_open_wim(const char *wim_file, int open_flags,
- WIMStruct **w_ret)
+ WIMStruct **w_ret,
+ wimlib_progress_func_t progress_func)
{
WIMStruct *w;
int ret;
- DEBUG("wim_file = `%s', open_flags = %#x", wim_file, open_flags);
+ if (!wim_file || !w_ret)
+ return WIMLIB_ERR_INVALID_PARAM;
w = new_wim_struct();
if (!w) {
ERROR("Failed to allocate memory for WIMStruct");
return WIMLIB_ERR_NOMEM;
}
- ret = begin_read(w, wim_file, open_flags);
+ ret = begin_read(w, wim_file, open_flags, progress_func);
if (ret == 0) {
*w_ret = w;
} else {
if (w->out_fp)
fclose(w->out_fp);
+#ifdef WITH_FUSE
if (w->fp_tab) {
for (size_t i = 0; i < w->num_allocated_fps; i++)
if (w->fp_tab[i])
FREE(w->fp_tab);
}
pthread_mutex_destroy(&w->fp_tab_mutex);
+#endif
free_lookup_table(w->lookup_table);
#endif
FREE(w);
}
-