]> wimlib.net Git - wimlib/blobdiff - src/wim.c
Update wimlib.h documentation
[wimlib] / src / wim.c
index ed6ab33d97650ad4dcf50a70e7280130f62b8ef5..500fc1ebc08f7407028be9041fb9f2defe7fbbe2 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -30,6 +30,8 @@
 #include <stdarg.h>
 
 #include "dentry.h"
+#include <unistd.h>
+#include <fcntl.h>
 
 #ifdef WITH_NTFS_3G
 #include <time.h>
@@ -72,7 +74,7 @@ WIMStruct *new_wim_struct()
 }
 
 /*
- * 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.
@@ -84,7 +86,7 @@ int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *))
        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) {
@@ -130,7 +132,8 @@ static int append_metadata_resource_entry(struct lookup_table_entry *lte,
 
        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 {
@@ -150,13 +153,13 @@ int wim_hdr_flags_compression_type(int wim_hdr_flags)
 {
        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;
        }
 }
 
@@ -214,10 +217,9 @@ int select_wim_image(WIMStruct *w, int image)
                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);
@@ -252,11 +254,11 @@ WIMLIBAPI int wimlib_get_compression_type(const WIMStruct *w)
 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";
@@ -274,16 +276,16 @@ WIMLIBAPI int wimlib_resolve_image(WIMStruct *w, const char *image_name_or_num)
        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++) {
@@ -291,7 +293,7 @@ WIMLIBAPI int wimlib_resolve_image(WIMStruct *w, const char *image_name_or_num)
                                   wimlib_get_image_name(w, i)) == 0)
                                return i;
                }
-               return WIM_NO_IMAGE;
+               return WIMLIB_NO_IMAGE;
        }
 }
 
@@ -330,7 +332,7 @@ WIMLIBAPI void wimlib_print_available_images(const WIMStruct *w, int 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;
@@ -351,8 +353,8 @@ WIMLIBAPI void wimlib_print_available_images(const WIMStruct *w, int image)
 }
 
 
-/* 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)
@@ -391,6 +393,17 @@ WIMLIBAPI int wimlib_set_boot_idx(WIMStruct *w, int boot_idx)
        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;
 }
 
@@ -407,34 +420,71 @@ WIMLIBAPI int wimlib_get_boot_idx(const WIMStruct *w)
        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.
  */
-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;
 
        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_WITH_ERRNO("Failed to resolve WIM filename");
-               return WIMLIB_ERR_NOMEM;
+               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);
 
@@ -446,38 +496,37 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
                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));
@@ -485,7 +534,8 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
        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;
 
@@ -496,7 +546,7 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
                                     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) */
@@ -505,10 +555,10 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
        {
                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
@@ -516,16 +566,14 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
        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) {
@@ -533,11 +581,34 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
                      "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 = 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;*/
+out:
+       return ret;
 }
 
 
@@ -545,7 +616,8 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags)
  * 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;
@@ -557,7 +629,7 @@ WIMLIBAPI int wimlib_open_wim(const char *wim_file, int open_flags,
                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 {
@@ -608,4 +680,3 @@ WIMLIBAPI void wimlib_free(WIMStruct *w)
 #endif
        FREE(w);
 }
-