split WIM apply, doc updates
authorEric Biggers <ebiggers3@gmail.com>
Fri, 31 Aug 2012 22:31:56 +0000 (17:31 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Fri, 31 Aug 2012 22:31:56 +0000 (17:31 -0500)
12 files changed:
programs/imagex.c
src/extract.c
src/join.c
src/lookup_table.c
src/modify.c
src/ntfs-apply.c
src/split.c
src/wim.c
src/wimlib.h
src/wimlib_internal.h
src/write.c
src/xml.c

index 5c5d42bc0733e444f8095059afca97c5a257bebb..12bfbc6201e888c839073c2611adc0266e7674af 100644 (file)
@@ -27,6 +27,7 @@
 #include <getopt.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <glob.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/stat.h>
@@ -134,6 +135,7 @@ static const struct option apply_options[] = {
        {"hardlink", no_argument,       NULL, 'h'},
        {"symlink",  no_argument,       NULL, 's'},
        {"verbose",  no_argument,       NULL, 'v'},
+       {"ref",      required_argument, NULL, 'r'},
        {NULL, 0, NULL, 0},
 };
 static const struct option capture_options[] = {
@@ -444,7 +446,8 @@ out:
 static int imagex_apply(int argc, const char **argv)
 {
        int c;
-       int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS;
+       int open_flags = WIMLIB_OPEN_FLAG_SHOW_PROGRESS |
+                        WIMLIB_OPEN_FLAG_SPLIT_OK;
        int image;
        int num_images;
        WIMStruct *w;
@@ -454,6 +457,11 @@ static int imagex_apply(int argc, const char **argv)
        const char *image_num_or_name;
        int extract_flags = 0;
 
+       const char *swm_glob = NULL;
+       WIMStruct **additional_swms = NULL;
+       size_t num_additional_swms = 0;
+       glob_t globbuf;
+
        for_opt(c, apply_options) {
                switch (c) {
                case 'c':
@@ -468,6 +476,9 @@ static int imagex_apply(int argc, const char **argv)
                case 'v':
                        extract_flags |= WIMLIB_EXTRACT_FLAG_VERBOSE;
                        break;
+               case 'r':
+                       swm_glob = optarg;
+                       break;
                default:
                        usage(APPLY);
                        return -1;
@@ -491,7 +502,7 @@ static int imagex_apply(int argc, const char **argv)
 
        ret = wimlib_open_wim(wimfile, open_flags, &w);
        if (ret != 0)
-               goto out;
+               return ret;
 
        image = wimlib_resolve_image(w, image_num_or_name);
        ret = verify_image_exists(image);
@@ -507,6 +518,36 @@ static int imagex_apply(int argc, const char **argv)
                goto out;
        }
 
+       if (swm_glob) {
+               ret = glob(swm_glob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
+               if (ret != 0) {
+                       imagex_error_with_errno("Failed to process glob "
+                                               "\"%s\"", swm_glob);
+                       ret = -1;
+                       goto out;
+               }
+               num_additional_swms = globbuf.gl_pathc;
+               additional_swms = calloc(num_additional_swms, sizeof(additional_swms[0]));
+               if (!additional_swms) {
+                       imagex_error("Out of memory");
+                       ret = -1;
+                       goto out;
+               }
+               size_t offset = 0;
+               for (size_t i = 0; i < num_additional_swms; i++) {
+                       if (strcmp(globbuf.gl_pathv[i], wimfile) == 0) {
+                               offset++;
+                               continue;
+                       }
+                       ret = wimlib_open_wim(globbuf.gl_pathv[i],
+                                             open_flags | WIMLIB_OPEN_FLAG_SPLIT_OK,
+                                             &additional_swms[i - offset]);
+                       if (ret != 0)
+                               goto out;
+               }
+               num_additional_swms -= offset;
+       }
+
 #ifdef WITH_NTFS_3G
        struct stat stbuf;
 
@@ -518,7 +559,9 @@ static int imagex_apply(int argc, const char **argv)
                               image, wimfile, ntfs_device);
                        ret = wimlib_apply_image_to_ntfs_volume(w, image,
                                                                ntfs_device,
-                                                               extract_flags);
+                                                               extract_flags,
+                                                               additional_swms,
+                                                               num_additional_swms);
                        goto out;
                }
        } else {
@@ -527,9 +570,13 @@ static int imagex_apply(int argc, const char **argv)
        }
 #endif
 
-       ret = wimlib_extract_image(w, image, dir, extract_flags);
+       ret = wimlib_extract_image(w, image, dir, extract_flags,
+                                  additional_swms, num_additional_swms);
 out:
        wimlib_free(w);
+       if (additional_swms)
+               for (size_t i = 0; i < num_additional_swms; i++)
+                       wimlib_free(additional_swms[i]);
        return ret;
 }
 
index 1d755cff6280161c84a322664d665333d8966602..e42aba4d1f6d0bb8975f62088e5554fb7f34588d 100644 (file)
@@ -393,25 +393,54 @@ static int extract_all_images(WIMStruct *w, const char *output_dir,
        return 0;
 }
 
+
 /* Extracts a single image or all images from a WIM file. */
 WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image,
-                                  const char *output_dir, int flags)
+                                  const char *output_dir, int flags,
+                                  WIMStruct **additional_swms,
+                                  unsigned num_additional_swms)
 {
-       if (!output_dir)
+       struct lookup_table *joined_tab, *w_tab_save;
+       int ret;
+
+       DEBUG("w->filename = %s, image = %d, output_dir = %s, flags = 0x%x, "
+             "num_additional_swms = %u",
+             w->filename, image, output_dir, flags, num_additional_swms);
+
+       if (!w || !output_dir)
                return WIMLIB_ERR_INVALID_PARAM;
 
        if ((flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK))
                        == (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK))
                return WIMLIB_ERR_INVALID_PARAM;
 
+       ret = verify_swm_set(w, additional_swms, num_additional_swms);
+       if (ret != 0)
+               return ret;
+
+       if (num_additional_swms) {
+               ret = new_joined_lookup_table(w, additional_swms,
+                                             num_additional_swms, &joined_tab);
+               if (ret != 0)
+                       return ret;
+               w_tab_save = w->lookup_table;
+               w->lookup_table = joined_tab;
+       }
+
+
        for_lookup_table_entry(w->lookup_table, zero_out_refcnts, NULL);
 
        if (image == WIM_ALL_IMAGES) {
                flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE;
-               return extract_all_images(w, output_dir, flags);
+               ret = extract_all_images(w, output_dir, flags);
        } else {
                flags &= ~WIMLIB_EXTRACT_FLAG_MULTI_IMAGE;
-               return extract_single_image(w, image, output_dir, flags);
+               ret = extract_single_image(w, image, output_dir, flags);
+       }
+       if (num_additional_swms) {
+               free_lookup_table(w->lookup_table);
+               w->lookup_table = w_tab_save;
        }
+       return ret;
 
 }
index 1d895cf8ccfec348333afbae66cd9657420ccfdc..3710eec85ec72ec02fee1bae2d857cf328fd79b2 100644 (file)
 #include "wimlib_internal.h"
 #include "lookup_table.h"
 #include "xml.h"
+#include <stdlib.h>
+
+static int copy_lte_to_table(struct lookup_table_entry *lte, void *table)
+{
+       struct lookup_table_entry *copy;
+       copy = new_lookup_table_entry();
+       if (!copy)
+               return WIMLIB_ERR_NOMEM;
+       memcpy(copy, lte, sizeof(struct lookup_table_entry));
+       lookup_table_insert(table, copy);
+       return 0;
+}
+
+static int lookup_table_join(struct lookup_table *table,
+                            struct lookup_table *new)
+{
+       return for_lookup_table_entry(new, copy_lte_to_table, table);
+}
+
+
+static int cmp_swms_by_part_number(const void *swm1, const void *swm2)
+{
+       u16 partno_1 = (*(WIMStruct**)swm1)->hdr.part_number;
+       u16 partno_2 = (*(WIMStruct**)swm2)->hdr.part_number;
+       return (int)partno_1 - (int)partno_2;
+}
+
+int verify_swm_set(WIMStruct *w, WIMStruct **additional_swms,
+                  unsigned num_additional_swms)
+{
+       unsigned total_parts = w->hdr.total_parts;
+       int ctype;
+       const u8 *guid;
+
+       if (total_parts != num_additional_swms + 1) {
+               ERROR("`%s' says there are %u parts in the spanned set, "
+                     "but %s%u part%s provided",
+                     w->filename, w->hdr.total_parts,
+                     (num_additional_swms + 1 < w->hdr.total_parts) ? "only " : "",
+                     num_additional_swms + 1,
+                     (num_additional_swms) ? "s were" : " was");
+               return WIMLIB_ERR_SPLIT_INVALID;
+       }
+       if (w->hdr.part_number != 1) {
+               ERROR("WIM `%s' is not the first part of the split WIM.",
+                     w->filename);
+               return WIMLIB_ERR_SPLIT_INVALID;
+       }
+       for (unsigned i = 0; i < num_additional_swms; i++) {
+               if (additional_swms[i]->hdr.total_parts != total_parts) {
+                       ERROR("WIM `%s' says there are %u parts in the spanned set, "
+                             "but %u parts were provided", 
+                             additional_swms[i]->filename,
+                             additional_swms[i]->hdr.total_parts,
+                             total_parts);
+                       return WIMLIB_ERR_SPLIT_INVALID;
+               }
+       }
+
+       /* keep track of ctype and guid just to make sure they are the same for
+        * all the WIMs. */
+       ctype = wimlib_get_compression_type(w);
+       guid = w->hdr.guid;
+
+       WIMStruct *parts_to_swms[num_additional_swms];
+       ZERO_ARRAY(parts_to_swms);
+       for (unsigned i = 0; i < num_additional_swms; i++) {
+
+               WIMStruct *swm = additional_swms[i];
+
+               if (wimlib_get_compression_type(swm) != ctype) {
+                       ERROR("The split WIMs do not all have the same "
+                             "compression type");
+                       return WIMLIB_ERR_SPLIT_INVALID;
+               }
+               if (memcmp(guid, swm->hdr.guid, WIM_GID_LEN) != 0) {
+                       ERROR("The split WIMs do not all have the same "
+                             "GUID");
+                       return WIMLIB_ERR_SPLIT_INVALID;
+               }
+               if (swm->hdr.part_number == 1) {
+                       ERROR("WIMs `%s' and `%s' both are marked as the "
+                             "first WIM in the spanned set", 
+                             w->filename, swm->filename);
+                       return WIMLIB_ERR_SPLIT_INVALID;
+               }
+               if (swm->hdr.part_number == 0 ||
+                   swm->hdr.part_number > total_parts)
+               {
+                       ERROR("WIM `%s' says it is part %u in the spanned set, "
+                             "but the part number must be in the range "
+                             "[1, %u]",
+                             swm->filename, swm->hdr.part_number, total_parts);
+                       return WIMLIB_ERR_SPLIT_INVALID;
+               }
+               if (parts_to_swms[swm->hdr.part_number - 2])
+               {
+                       ERROR("`%s' and `%s' are both marked as part %u of %u "
+                             "in the spanned set",
+                             parts_to_swms[swm->hdr.part_number - 2]->filename,
+                             swm->filename,
+                             swm->hdr.part_number,
+                             total_parts);
+                       return WIMLIB_ERR_SPLIT_INVALID;
+               } else {
+                       parts_to_swms[swm->hdr.part_number - 2] = swm;
+               }
+       }
+       return 0;
+}
+
+int new_joined_lookup_table(WIMStruct *w,
+                           WIMStruct **additional_swms,
+                           unsigned num_additional_swms,
+                           struct lookup_table **table_ret)
+{
+       struct lookup_table *table;
+       int ret;
+       unsigned i;
+
+
+       table = new_lookup_table(9001);
+       if (!table)
+               return WIMLIB_ERR_NOMEM;
+       ret = lookup_table_join(table, w->lookup_table);
+       if (ret != 0)
+               goto out_free_table;
+       for (i = 0; i < num_additional_swms; i++) {
+               ret = lookup_table_join(table, additional_swms[i]->lookup_table);
+               if (ret != 0)
+                       goto out_free_table;
+       }
+       *table_ret = table;
+       return 0;
+out_free_table:
+       free_lookup_table(table);
+       return ret;
+}
+
 
 static int join_wims(WIMStruct **swms, uint num_swms, WIMStruct *joined_wim,
                     int write_flags)
@@ -105,81 +244,46 @@ static int join_wims(WIMStruct **swms, uint num_swms, WIMStruct *joined_wim,
 }
 
 
-WIMLIBAPI int wimlib_join(const char **swm_names, int num_swms, 
+WIMLIBAPI int wimlib_join(const char **swm_names, unsigned num_swms, 
                          const char *output_path, int flags)
 {
        int i;
        int ret;
        int part_idx;
        int write_flags = 0;
-       WIMStruct *w;
        WIMStruct *joined_wim = NULL;
        WIMStruct *swms[num_swms];
 
-       /* keep track of ctype and guid just to make sure they are the same for
-        * all the WIMs. */
        int ctype;
        u8 *guid;
 
+       if (num_swms < 1)
+               return WIMLIB_ERR_INVALID_PARAM;
+
        ZERO_ARRAY(swms);
+
        for (i = 0; i < num_swms; i++) {
                ret = wimlib_open_wim(swm_names[i], 
-                                     flags | WIMLIB_OPEN_FLAG_SPLIT_OK, &w);
+                                     flags | WIMLIB_OPEN_FLAG_SPLIT_OK, &swms[i]);
                if (ret != 0)
-                       goto err;
+                       goto out;
 
                /* don't open all the parts at the same time, in case there are
                 * a lot of them */
-               fclose(w->fp);
-               w->fp = NULL;
+               fclose(swms[i]->fp);
+               swms[i]->fp = NULL;
+       }
 
-               if (i == 0) {
-                       ctype = wimlib_get_compression_type(w);
-                       guid = w->hdr.guid;
-               } else {
-                       if (wimlib_get_compression_type(w) != ctype) {
-                               ERROR("The split WIMs do not all have the same "
-                                     "compression type");
-                               ret = WIMLIB_ERR_SPLIT_INVALID;
-                               goto err;
-                       }
-                       if (memcmp(guid, w->hdr.guid, WIM_GID_LEN) != 0) {
-                               ERROR("The split WIMs do not all have the same "
-                                     "GUID");
-                               ret = WIMLIB_ERR_SPLIT_INVALID;
-                               goto err;
-                       }
-               }
-               if (w->hdr.total_parts != num_swms) {
-                       ERROR("`%s' (part %d) says there are %d total parts, "
-                             "but %d parts were specified",
-                             swm_names[i], w->hdr.part_number,
-                             w->hdr.total_parts, num_swms);
-                       ret = WIMLIB_ERR_SPLIT_INVALID;
-                       goto err;
-               }
-               if (w->hdr.part_number == 0 || w->hdr.part_number > num_swms) {
-                       ERROR("`%s' says it is part %d, but expected a number "
-                             "between 1 and %d",
-                             swm_names[i], w->hdr.part_number, num_swms);
-                       ret = WIMLIB_ERR_SPLIT_INVALID;
-                       goto err;
-               }
-               part_idx = w->hdr.part_number - 1;
-               if (swms[part_idx] != NULL) {
-                       ERROR("`%s' and `%s' both say they are part %d of %d",
-                             swm_names[i], swms[part_idx]->filename,
-                             w->hdr.part_number, num_swms);
-                       ret = WIMLIB_ERR_SPLIT_INVALID;
-                       goto err;
-               }
-               swms[part_idx] = w;
+       qsort(swms, num_swms, sizeof(swms[0]), cmp_swms_by_part_number);
+
+       ret = verify_swm_set(swms[0], &swms[1], num_swms - 1);
+       if (ret != 0)
+               goto out;
 
-       }
        joined_wim = new_wim_struct();
        if (!joined_wim) {
                ret = WIMLIB_ERR_NOMEM;
-               goto err;
+               goto out;
        }
 
        if (flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY)
@@ -189,9 +293,9 @@ WIMLIBAPI int wimlib_join(const char **swm_names, int num_swms,
 
        ret = begin_write(joined_wim, output_path, write_flags);
        if (ret != 0)
-               goto err;
+               goto out;
        ret = join_wims(swms, num_swms, joined_wim, write_flags);
-err:
+out:
        for (i = 0; i < num_swms; i++) {
                /* out_fp is the same in all the swms and joined_wim; only close
                 * it one time, when freeing joined_wim. */
index c1dca74f6d83f3d6c17fc8c5c118de4db610a918..5408baf654a80756411ff51e18c9404b69e894bb 100644 (file)
@@ -113,7 +113,7 @@ static int do_free_lookup_table_entry(struct lookup_table_entry *entry,
 
 void free_lookup_table(struct lookup_table *table)
 {
-       DEBUG("Freeing lookup table");
+       DEBUG2("Freeing lookup table");
        if (table) {
                if (table->array) {
                        for_lookup_table_entry(table,
@@ -200,6 +200,7 @@ int read_lookup_table(WIMStruct *w)
        u8     buf[WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE];
        int    ret;
        struct lookup_table *table;
+       struct lookup_table_entry *cur_entry = NULL, *duplicate_entry;
 
        DEBUG("Reading lookup table: offset %"PRIu64", size %"PRIu64"",
              w->hdr.lookup_table_res_entry.offset,
@@ -220,7 +221,6 @@ int read_lookup_table(WIMStruct *w)
 
        while (num_entries--) {
                const u8 *p;
-               struct lookup_table_entry *cur_entry, *duplicate_entry;
 
                if (fread(buf, 1, sizeof(buf), w->fp) != sizeof(buf)) {
                        if (feof(w->fp)) {
@@ -245,12 +245,20 @@ int read_lookup_table(WIMStruct *w)
                p = get_u32(p, &cur_entry->refcnt);
                p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
 
+               if (cur_entry->part_number != w->hdr.part_number) {
+                       ERROR("A lookup table entry in part %hu of the WIM "
+                             "points to part %hu",
+                             w->hdr.part_number, cur_entry->part_number);
+                       ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+                       goto out_free_cur_entry;
+                       
+               }
+
                if (is_zero_hash(cur_entry->hash)) {
                        ERROR("The WIM lookup table contains an entry with a "
                              "SHA1 message digest of all 0's");
                        ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
-                       FREE(cur_entry);
-                       goto out;
+                       goto out_free_cur_entry;
                }
 
                duplicate_entry = __lookup_resource(table, cur_entry->hash);
@@ -262,10 +270,8 @@ int read_lookup_table(WIMStruct *w)
                        ERROR("The second entry is:");
                        print_lookup_table_entry(cur_entry);
                        ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
-                       FREE(cur_entry);
-                       goto out;
+                       goto out_free_cur_entry;
                }
-               lookup_table_insert(table, cur_entry);
 
                if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED)
                    && (cur_entry->resource_entry.size !=
@@ -276,12 +282,16 @@ int read_lookup_table(WIMStruct *w)
                        ERROR("The lookup table entry for the resource is as follows:");
                        print_lookup_table_entry(cur_entry);
                        ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
-                       goto out;
+                       goto out_free_cur_entry;
                }
+               lookup_table_insert(table, cur_entry);
+
        }
        DEBUG("Done reading lookup table.");
        w->lookup_table = table;
        return 0;
+out_free_cur_entry:
+       FREE(cur_entry);
 out:
        free_lookup_table(table);
        return ret;
index 3dc0de44542827cb5f6f1cf30c75a20515840cd3..5223b81912c5abde8943a9d2c85023ca814029cd 100644 (file)
@@ -364,6 +364,15 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim,
        struct wim_pair wims;
        struct wim_security_data *sd;
 
+       if (!src_wim || !dest_wim)
+               return WIMLIB_ERR_INVALID_PARAM;
+
+       if (src_wim->hdr.total_parts != 1 || src_wim->hdr.total_parts != 1) {
+               ERROR("Exporting an image to or from a split WIM is "
+                     "unsupported");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
+
        if (src_image == WIM_ALL_IMAGES) {
                if (src_wim->hdr.image_count > 1) {
 
@@ -466,6 +475,11 @@ WIMLIBAPI int wimlib_delete_image(WIMStruct *w, int image)
        int i;
        int ret;
 
+       if (w->hdr.total_parts != 1) {
+               ERROR("Deleting an image from a split WIM is not supported.");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
+
        if (image == WIM_ALL_IMAGES) {
                num_images = w->hdr.image_count;
                for (i = 1; i <= num_images; i++) {
@@ -791,6 +805,11 @@ int do_add_image(WIMStruct *w, const char *dir, const char *name,
                return WIMLIB_ERR_INVALID_PARAM;
        }
 
+       if (w->hdr.total_parts != 1) {
+               ERROR("Cannot add an image to a split WIM");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
+
        if (wimlib_image_name_in_use(w, name)) {
                ERROR("There is already an image named \"%s\" in `%s'",
                      name, w->filename);
index ee1982af7f63d610676f59363fede5d46b94650e..7ae7fa17316297cdbf70f130ac4d876918e32fb1 100644 (file)
@@ -729,11 +729,18 @@ out:
  * full filesystem to be applied to the volume.
  */
 WIMLIBAPI int wimlib_apply_image_to_ntfs_volume(WIMStruct *w, int image,
-                                               const char *device, int flags)
+                                               const char *device, int flags,
+                                               WIMStruct **additional_swms,
+                                               unsigned num_additional_swms)
 {
+       struct lookup_table *joined_tab, *w_tab_save;
        int ret;
 
-       if (!device)
+       DEBUG("w->filename = %s, image = %d, device = %s, flags = 0x%x, "
+             "num_additional_swms = %u",
+             w->filename, image, device, flags, num_additional_swms);
+
+       if (!w || !device)
                return WIMLIB_ERR_INVALID_PARAM;
        if (image == WIM_ALL_IMAGES) {
                ERROR("Can only apply a single image when applying "
@@ -745,16 +752,39 @@ WIMLIBAPI int wimlib_apply_image_to_ntfs_volume(WIMStruct *w, int image,
                ERROR("directly to a NTFS volume");
                return WIMLIB_ERR_INVALID_PARAM;
        }
-       ret = wimlib_select_image(w, image);
+
+       ret = verify_swm_set(w, additional_swms, num_additional_swms);
        if (ret != 0)
                return ret;
 
-       return do_wim_apply_image_ntfs(w, device, flags);
+       if (num_additional_swms) {
+               ret = new_joined_lookup_table(w, additional_swms,
+                                             num_additional_swms, &joined_tab);
+               if (ret != 0)
+                       return ret;
+               w_tab_save = w->lookup_table;
+               w->lookup_table = joined_tab;
+       }
+
+       ret = wimlib_select_image(w, image);
+       if (ret != 0)
+               goto out;
+
+       ret = do_wim_apply_image_ntfs(w, device, flags);
+
+out:
+       if (num_additional_swms) {
+               free_lookup_table(w->lookup_table);
+               w->lookup_table = w_tab_save;
+       }
+       return ret;
 }
 
 #else /* WITH_NTFS_3G */
 WIMLIBAPI int wimlib_apply_image_to_ntfs_volume(WIMStruct *w, int image,
-                                               const char *device, int flags)
+                                               const char *device, int flags,
+                                               WIMStruct **additional_swms,
+                                               unsigned num_additional_swms)
 {
        ERROR("wimlib was compiled without support for NTFS-3g, so");
        ERROR("we cannot apply a WIM image directly to a NTFS volume");
index f9811d97dd69ee57fc879e7d4d93ce724d9b1116..b8cb67896e57743eec0e768455260f9c76dbfcdd 100644 (file)
@@ -53,8 +53,6 @@ static int finish_swm(WIMStruct *w, struct lookup_table_entry *lte_chain_head,
                        lookup_table_offset);
 
        while (lte_chain_head != NULL) {
-               print_lookup_table_entry(lte_chain_head);
-
                ret = write_lookup_table_entry(lte_chain_head, w->out_fp);
                if (ret != 0)
                        return ret;
index 1a159578a0338da0ac08ba61e8de2524f7eec6a1..5d5c8fefb3a0dcfa6c0261216b02a0a95ed19f3b 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -328,6 +328,14 @@ WIMLIBAPI void wimlib_print_available_images(const WIMStruct *w, int image)
  * not WIM_NO_IMAGE. */
 WIMLIBAPI int wimlib_print_metadata(WIMStruct *w, int image)
 {
+       if (!w)
+               return WIMLIB_ERR_INVALID_PARAM;
+       if (w->hdr.part_number != 1) {
+               ERROR("We cannot show the metadata from part %hu of a %hu-part split WIM",
+                      w->hdr.part_number, w->hdr.total_parts);
+               ERROR("Select the first part of the split WIM to see the metadata.");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
        if (image == WIM_ALL_IMAGES)
                DEBUG("Printing metadata for all images");
        else
@@ -337,12 +345,26 @@ WIMLIBAPI int wimlib_print_metadata(WIMStruct *w, int image)
 
 WIMLIBAPI int wimlib_print_files(WIMStruct *w, int image)
 {
+       if (!w)
+               return WIMLIB_ERR_INVALID_PARAM;
+       if (w->hdr.part_number != 1) {
+               ERROR("We cannot list the files from part %hu of a %hu-part split WIM",
+                      w->hdr.part_number, w->hdr.total_parts);
+               ERROR("Select the first part of the split WIM if you'd like to list the files.");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
        return for_image(w, image, print_files);
 }
 
 /* Sets the index of the bootable image. */
 WIMLIBAPI int wimlib_set_boot_idx(WIMStruct *w, int boot_idx)
 {
+       if (!w)
+               return WIMLIB_ERR_INVALID_PARAM;
+       if (w->hdr.total_parts != 1) {
+               ERROR("We cannot modify the boot index of a split WIM");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
        if (boot_idx < 0 || boot_idx > w->hdr.image_count)
                return WIMLIB_ERR_INVALID_IMAGE;
        w->hdr.boot_idx = boot_idx;
@@ -535,7 +557,7 @@ WIMLIBAPI int wimlib_open_wim(const char *wim_file, int flags,
  * closes all files associated with the WIMStruct.  */
 WIMLIBAPI void wimlib_free(WIMStruct *w)
 {
-       DEBUG("Freeing WIMStruct");
+       DEBUG2("Freeing WIMStruct");
 
        if (!w)
                return;
index 2de733cda09083e79c31666b863b5547057cdf28..0debc5c249e03feea012b3747aab3564dd17ad30 100644 (file)
  * README for more information about installing it.  To use wimlib in a program
  * after installing it, include @c wimlib.h and link your program with @c -lwim.
  *
- * wimlib wraps up a WIM file in an opaque ::WIMStruct structure.
+ * wimlib wraps up a WIM file in an opaque ::WIMStruct structure.  A ::WIMStruct
+ * may represent either a stand-alone WIM or one part of a split WIM.
  *
  * All functions in wimlib's public API are prefixed with @c wimlib.  Most
  * return an integer error code on failure.  Use wimlib_get_error_string() to
  * get a string that describes an error code.  wimlib also can print error
  * messages itself when an error happens, and these may be more informative than
- * the error code; to enable this, call wimlib_set_print_errors().
+ * the error code; to enable this, call wimlib_set_print_errors().  Please note
+ * that this is for convenience only, and some errors can occur without a
+ * message being printed.
  *
  * wimlib is thread-safe as long as different ::WIMStruct's are used, with the
  * following exceptions:  wimlib_set_print_errors() and
  *
  * While wimlib supports the main features of WIM files, wimlib currently has
  * the following limitations:
- * - There is no way to directly extract or mount split WIMs.
  * - Different versions of the WIM file format are unsupported.  There is one
  *   different version of the format from development versions of Windows Vista,
  *   but I'm not planning to support it.
@@ -416,6 +418,9 @@ enum wimlib_error_code {
  * @retval ::WIMLIB_ERR_STAT
  *     Failed obtain the metadata for a file or directory in the directory tree
  *     rooted at @a dir.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim is part of a split WIM.  Adding an image to a split WIM is
+ *     unsupported.
  */
 extern int wimlib_add_image(WIMStruct *wim, const char *dir, 
                            const char *name, const char *config,
@@ -444,7 +449,9 @@ extern int wimlib_add_image_from_ntfs_volume(WIMStruct *w, const char *device,
  * the WIM.
  */
 extern int wimlib_apply_image_to_ntfs_volume(WIMStruct *w, int image,
-                                            const char *device, int flags);
+                                            const char *device, int flags,
+                                            WIMStruct **additional_swms,
+                                            unsigned num_additional_swms);
 
 /** 
  * Creates a WIMStruct for a new WIM file.
@@ -495,6 +502,9 @@ extern int wimlib_create_new_wim(int ctype, WIMStruct **wim_ret);
  * @retval ::WIMLIB_ERR_NOMEM Failed to allocate needed memory.
  * @retval ::WIMLIB_ERR_READ
  *     Could not read the metadata resource for @a image from the WIM.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim is part of a split WIM.  Deleting an image from a split WIM is
+ *     unsupported.
  */
 extern int wimlib_delete_image(WIMStruct *wim, int image);
 
@@ -548,7 +558,8 @@ extern int wimlib_delete_image(WIMStruct *wim, int image);
  *     ::WIM_ALL_IMAGES, @a src_wim contains multiple images, and no images in
  *     @a src_wim are marked as bootable; or @a dest_name and/or @a
  *     dest_description were non-<code>NULL</code>, @a src_image was
- *     ::WIM_ALL_IMAGES, and @a src_wim contains multiple images.
+ *     ::WIM_ALL_IMAGES, and @a src_wim contains multiple images; or @a src_wim
+ *     or @a dest_wim was @c NULL.
  * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE
  *     The metadata resource for @a src_image in @a src_wim is invalid.        
  * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA
@@ -557,25 +568,51 @@ extern int wimlib_delete_image(WIMStruct *wim, int image);
  *     Failed to allocate needed memory.
  * @retval ::WIMLIB_ERR_READ
  *     Could not read the metadata resource for @a src_image from @a src_wim.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a src_wim or @a dest_wim is part of a split WIM.  Exporting an image
+ *     from or to a split WIM is unsupported.
  */
 extern int wimlib_export_image(WIMStruct *src_wim, int src_image, 
                               WIMStruct *dest_wim, const char *dest_name, 
                               const char *dest_description, int flags);
 
 /**
- * Extracts an image, or all images, from a WIM file.
- *
- * The output directory must have been previously set with
- * wimlib_set_output_dir().
- *
- * The link type used for extracted files is that specified by a previous call
- * to wimlib_set_link_type(), or ::WIM_LINK_TYPE_NONE by default.
+ * Extracts an image, or all images, from a standalone or split WIM file.
  *
  * @param wim
- *     Pointer to the ::WIMStruct for a WIM file.
+ *     Pointer to the ::WIMStruct for a standalone WIM file, or part 1 of a
+ *     split WIM.
  * @param image
  *     The image to extract.  Can be the number of an image, or ::WIM_ALL_IMAGES
  *     to specify that all images are to be extracted.
+ * @param output_dir
+ *     Directory to extract the WIM image(s) to.  It is created if it does not
+ *     already exist.
+ * @param flags
+ *     Bitwise or of the flags prefixed with WIMLIB_EXTRACT_FLAG.
+ *
+ *     One or none of ::WIMLIB_EXTRACT_FLAG_HARDLINK or
+ *     ::WIMLIB_EXTRACT_FLAG_SYMLINK may be specified.  These flags cause
+ *     extracted files that are identical to be hardlinked or symlinked
+ *     together, depending on the flag.  These flags override the hard link
+ *     groups that are specified in the WIM file itself.  If ::WIM_ALL_IMAGES
+ *     is provided as the @a image parameter, files may be hardlinked or
+ *     symlinked across images if a file is found to occur in more than one
+ *     image.
+ *
+ *     You may also specify the flag ::WIMLIB_EXTRACT_FLAG_VERBOSE to cause
+ *     informational messages to be printed during the extraction, including
+ *     the name of each extracted file or directory.
+ * @param additional_swms
+ *     Array of pointers to the ::WIMStruct for each additional part in the
+ *     split WIM.  Ignored if @a num_additional_swms is 0.  The pointers do not
+ *     need to be in any particular order, but they must include all parts of
+ *     the split WIM other than the first part, which must be provided in the
+ *     @a wim parameter.
+ * @param num_additional_swms
+ *     Number of additional WIM parts provided in the @a additional_swms array.
+ *     This number should be one less than the total number of parts in the
+ *     split WIM.
  *
  * @return 0 on success; nonzero on error.
  * @retval ::WIMLIB_ERR_DECOMPRESSION
@@ -602,15 +639,23 @@ extern int wimlib_export_image(WIMStruct *src_wim, int src_image,
  * @retval ::WIMLIB_ERR_READ
  *     A unexpected end-of-file or read error occurred when trying to read data
  *     from the WIM file associated with @a wim.
+ * @retval ::WIMLIB_ERR_SPLIT_INVALID
+ *     The WIM is a split WIM, but the parts specified do not form a complete
+ *     split WIM because they do not include all the parts of the original WIM,
+ *     there are duplicate parts, or not all the parts have the same GUID and
+ *     compression type.
  * @retval ::WIMLIB_ERR_WRITE
  *     Failed to write a file being extracted.
  */
 extern int wimlib_extract_image(WIMStruct *wim, int image,
-                               const char *output_dir, int flags);
+                               const char *output_dir, int flags,
+                               WIMStruct **additional_swms,
+                               unsigned num_additional_swms);
 
 /**
  * Extracts the XML data for a WIM file to a file stream.  Every WIM file
  * includes a string of XML that describes the images contained in the WIM.
+ * This function works on standalone WIMs as well as split WIM parts.
  *
  * @param wim
  *     Pointer to the ::WIMStruct for a WIM file.
@@ -687,7 +732,8 @@ extern const char *wimlib_get_error_string(enum wimlib_error_code code);
  * Returns the description of the specified image.
  *
  * @param wim
- *     Pointer to the ::WIMStruct for a WIM file.
+ *     Pointer to the ::WIMStruct for a WIM file.  It may be either a
+ *     standalone WIM or a split WIM part.
  * @param image
  *     The number of the image, numbered starting at 1.
  *
@@ -701,7 +747,8 @@ extern const char *wimlib_get_image_description(const WIMStruct *wim, int image)
  * Returns the name of the specified image.
  *
  * @param wim
- *     Pointer to the ::WIMStruct for a WIM file.
+ *     Pointer to the ::WIMStruct for a WIM file.  It may be either a
+ *     standalone WIM or a split WIM part.
  * @param image
  *     The number of the image, numbered starting at 1.
  *
@@ -715,7 +762,8 @@ extern const char *wimlib_get_image_name(const WIMStruct *wim, int image);
  * Gets the number of images contained in the WIM.
  *
  * @param wim
- *     Pointer to the ::WIMStruct for a WIM file.
+ *     Pointer to the ::WIMStruct for a WIM file.  It may be either a
+ *     standalone WIM or a split WIM part.
  * 
  * @return
  *     The number of images contained in the WIM file.
@@ -723,7 +771,7 @@ extern const char *wimlib_get_image_name(const WIMStruct *wim, int image);
 extern int wimlib_get_num_images(const WIMStruct *wim);
 
 /**
- * Gets the part number of the wim (in a split WIM).
+ * Gets the part number of part of a split WIM.
  *
  * @param wim
  *     Pointer to the ::WIMStruct for a WIM file.
@@ -742,7 +790,7 @@ extern int wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret);
  * @param wim
  *     Pointer to the ::WIMStruct for a WIM file.
  * @return
- *     @c true if the WIM has an integrity table; false otherwise.
+ *     @c true if the WIM has an integrity table; @c false otherwise.
  */
 extern bool wimlib_has_integrity_table(const WIMStruct *wim);
 
@@ -790,7 +838,7 @@ extern bool wimlib_image_name_in_use(const WIMStruct *wim, const char *name);
  * Note that this function merely copies the resources, so it will not check to
  * see if the resources, including the metadata resource, are valid or not.
  */
-extern int wimlib_join(const char **swms, int num_swms,
+extern int wimlib_join(const char **swms, unsigned num_swms,
                       const char *output_path, int flags);
 
 /**
@@ -846,7 +894,6 @@ extern int wimlib_join(const char **swms, int num_swms,
  * @retval ::WIMLIB_ERR_READ
  *     An unexpected end-of-file or read error occurred when trying to read
  *     data from the WIM file associated with @a wim.
- *
  */
 extern int wimlib_mount(WIMStruct *wim, int image, const char *dir, int flags);
 
@@ -1031,6 +1078,8 @@ extern void wimlib_print_available_images(const WIMStruct *wim, int image);
  * @retval ::WIMLIB_ERR_INVALID_IMAGE
  *     @a image does not specify a valid image in @a wim, and is not
  *     ::WIM_ALL_IMAGES.
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ *     @a wim was @c NULL.
  * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE
  *     The metadata resource for one of the specified images is invalid.
  * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA
@@ -1040,6 +1089,9 @@ extern void wimlib_print_available_images(const WIMStruct *wim, int image);
  * @retval ::WIMLIB_ERR_READ
  *     An unexpected read error or end-of-file occurred when reading the
  *     metadata resource for one of the specified images.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim was not a standalone WIM and was not the first part of a split
+ *     WIM.
  */
 extern int wimlib_print_files(WIMStruct *wim, int image);
 
@@ -1047,7 +1099,8 @@ extern int wimlib_print_files(WIMStruct *wim, int image);
  * Prints detailed information from the header of a WIM file.
  *
  * @param wim
- *     Pointer to the ::WIMStruct for a WIM file.
+ *     Pointer to the ::WIMStruct for a WIM file.  It may be either a
+ *     standalone WIM or part of a split WIM.
  *
  * @return This function has no return value.
  *
@@ -1089,6 +1142,8 @@ extern void wimlib_print_lookup_table(WIMStruct *wim);
  * @retval ::WIMLIB_ERR_INVALID_IMAGE
  *     @a image does not specify a valid image in @a wim, and is not
  *     ::WIM_ALL_IMAGES.
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ *     @a wim was @c NULL.
  * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE
  *     The metadata resource for one of the specified images is invalid.
  * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA
@@ -1098,6 +1153,9 @@ extern void wimlib_print_lookup_table(WIMStruct *wim);
  * @retval ::WIMLIB_ERR_READ
  *     An unexpected read error or end-of-file occurred when reading the
  *     metadata resource for one of the specified images.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim was not a standalone WIM and was not the first part of a split
+ *     WIM.
  */
 extern int wimlib_print_metadata(WIMStruct *wim, int image);
 
@@ -1144,9 +1202,14 @@ extern int wimlib_resolve_image(WIMStruct *wim, const char *image_name_or_num);
  *     The number of the image to mark as bootable, or 0 to mark no image as
  *     bootable.
  * @return 0 on success; nonzero on error.
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ *     @a wim was @c NULL.
  * @retval ::WIMLIB_ERR_INVALID_IMAGE 
  *     @a boot_idx does not specify an existing image in @a wim, and it was not
  *     0.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim is part of a split WIM.  We do not support changing the boot
+ *     index of a split WIM.
  */
 extern int wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
 
@@ -1154,7 +1217,9 @@ extern int wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
  * Changes the description of an image in the WIM.
  *
  * @param wim
- *     Pointer to the ::WIMStruct for a WIM file.
+ *     Pointer to the ::WIMStruct for a WIM file.  It may be either a
+ *     standalone WIM or part of a split WIM; however, you should set the same
+ *     description on all parts of a split WIM.
  * @param image
  *     The number of the image for which to change the description.
  * @param description
@@ -1164,6 +1229,8 @@ extern int wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
  * @return 0 on success; nonzero on error.
  * @retval ::WIMLIB_ERR_INVALID_IMAGE
  *     @a image does not specify a single existing image in @a wim.
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ *     @a wim was @c NULL.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @a description
  *     string.
@@ -1171,6 +1238,28 @@ extern int wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
 extern int wimlib_set_image_descripton(WIMStruct *wim, int image, 
                                       const char *description);
 
+/**
+ * Changes what is written in the <FLAGS> element in the WIM XML data (something
+ * like "Core" or "Ultimate")
+ *
+ * @param wim
+ *     Pointer to the ::WIMStruct for a WIM file.  It may be either a
+ *     standalone WIM or part of a split WIM; however, you should set the same
+ *     <FLAGS> element on all parts of a split WIM.
+ * @param image
+ *     The number of the image for which to change the description.
+ * @param flags
+ *     The new <FLAGS> element to give the image.  It may be @c NULL, which
+ *     indicates that the image is to be given no <FLAGS> element.
+ *
+ * @return 0 on success; nonzero on error.
+ * @retval ::WIMLIB_ERR_INVALID_IMAGE
+ *     @a image does not specify a single existing image in @a wim.
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ *     @a wim was @c NULL.
+ * @retval ::WIMLIB_ERR_NOMEM
+ *     Failed to allocate the memory needed to duplicate the @a flags string.
+ */
 extern int wimlib_set_image_flags(WIMStruct *w, int image,
                                  const char *flags);
 
@@ -1178,17 +1267,19 @@ extern int wimlib_set_image_flags(WIMStruct *w, int image,
  * Changes the name of an image in the WIM.
  *
  * @param wim
- *     Pointer to the ::WIMStruct for a WIM file.
+ *     Pointer to the ::WIMStruct for a WIM file.  It may be either a
+ *     standalone WIM or part of a split WIM; however, you should set the same
+ *     name on all parts of a split WIM.
  * @param image
  *     The number of the image for which to change the name.
  * @param name
- *     The new name to give the image.  It must not be @c NULL.
+ *     The new name to give the image.  It must not a nonempty string.
  *
  * @return 0 on success; nonzero on error.
  * @retval ::WIMLIB_ERR_IMAGE_NAME_COLLISION
  *     There is already an image named @a name in @a wim.
  * @retval ::WIMLIB_ERR_INVALID_PARAM
- *     @a name was @c NULL or the empty string.
+ *     @a name was @c NULL or the empty string, or @a wim was @c NULL.
  * @retval ::WIMLIB_ERR_INVALID_IMAGE
  *     @a image does not specify a single existing image in @a wim.
  * @retval ::WIMLIB_ERR_NOMEM
@@ -1204,6 +1295,9 @@ extern int wimlib_set_image_name(WIMStruct *wim, int image, const char *name);
  * The default is to use the default @c malloc() and @c free() from the C
  * library.
  *
+ * Please note that some external functions we call still may use the standard
+ * memory allocation functions.
+ *
  * @param malloc_func
  *     A function equivalent to @c malloc() that wimlib will use to allocate
  *     memory.  If @c NULL, the allocator function is set back to the default
@@ -1227,8 +1321,9 @@ int wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
 
 /**
  * Sets whether wimlib is to print error messages to @c stderr when a function
- * fails or not.  These error messages may provide information that cannot be
- * determined only from the error code that is returned.
+ * fails.  These error messages may provide information that cannot be
+ * determined only from the error code that is returned.  Not every error will
+ * result in an error message being printed.
  *
  * This setting is global and not per-WIM.
  *
@@ -1365,6 +1460,8 @@ extern int wimlib_unmount(const char *dir, int flags);
  *     A file that had previously been scanned for inclusion in the WIM by the
  *     wimlib_add_image() or wimlib_add_image_from_ntfs_volume() functions was
  *     concurrently modified, so it failed the SHA1 message digest check.
+ * @retval ::WIMLIB_ERR_INVALID_PARAM
+ *     @a wim or @a path was @c NULL.
  * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE
  *     The metadata resource for @a image in @a wim is invalid.        
  * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA
@@ -1380,6 +1477,9 @@ extern int wimlib_unmount(const char *dir, int flags);
  *     with @a wim, or some file resources in @a wim refer to files in the
  *     outside filesystem, and a read error occurred when reading one of these
  *     files.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim is part of a split WIM.  You may not call this function on a
+ *     split WIM.
  * @retval ::WIMLIB_ERR_WRITE
  *     An error occurred when trying to write data to the new WIM file at @a
  *     path.
index b90800bc32217fbc4935cb3d082d18451ebcabd8..fa40f6af80b9b6ba18fcae9b6c5a53e617f8c5ac 100644 (file)
@@ -354,6 +354,16 @@ extern int write_integrity_table(FILE *out, u64 end_header_offset,
                                 int show_progress);
 extern int check_wim_integrity(WIMStruct *w, int show_progress, int *status);
 
+/* join.c */
+
+extern int new_joined_lookup_table(WIMStruct *w,
+                                  WIMStruct **additional_swms,
+                                  unsigned num_additional_swms,
+                                  struct lookup_table **table_ret);
+
+extern int verify_swm_set(WIMStruct *w,
+                         WIMStruct **additional_swms,
+                         unsigned num_additional_swms);
 /* modify.c */
 extern void destroy_image_metadata(struct image_metadata *imd,
                                   struct lookup_table *lt);
index bc821fa7664b2561b5a1c6865644392163ecd0e6..497158999c807fb0ba6c0d0a8831a70f22f5b082 100644 (file)
@@ -60,6 +60,9 @@ WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int flags)
        size_t wim_name_len;
        int ret;
        
+       if (!w)
+               return WIMLIB_ERR_INVALID_PARAM;
+
        wimfile_name = w->filename;
 
        DEBUG("Replacing WIM file `%s'.", wimfile_name);
@@ -401,10 +404,19 @@ WIMLIBAPI int wimlib_write(WIMStruct *w, const char *path, int image, int flags)
 {
        int ret;
 
+       if (!w || !path)
+               return WIMLIB_ERR_INVALID_PARAM;
+
        if (image != WIM_ALL_IMAGES && 
             (image < 1 || image > w->hdr.image_count))
                return WIMLIB_ERR_INVALID_IMAGE;
 
+
+       if (w->hdr.total_parts != 1) {
+               ERROR("Cannot call wimlib_write() on part of a split WIM");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
+
        if (image == WIM_ALL_IMAGES)
                DEBUG("Writing all images to `%s'.", path);
        else
index 2f67c9851fcc8fe331a3c425cadee3e3d8dba2c7..73ba38e41f14b3f0be756048641d57610936098e 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -1356,6 +1356,9 @@ WIMLIBAPI int wimlib_set_image_name(WIMStruct *w, int image, const char *name)
 
        DEBUG("Setting the name of image %d to %s", image, name);
 
+       if (!w)
+               return WIMLIB_ERR_INVALID_PARAM;
+
        if (!name || !*name) {
                ERROR("Must specify a non-empty string for the image name");
                return WIMLIB_ERR_INVALID_PARAM;
@@ -1393,6 +1396,9 @@ WIMLIBAPI int wimlib_set_image_descripton(WIMStruct *w, int image,
 
        DEBUG("Setting the description of image %d to %s", image, description);
 
+       if (!w)
+               return WIMLIB_ERR_INVALID_PARAM;
+
        if (image < 1 || image > w->hdr.image_count) {
                ERROR("%d is not a valid image", image);
                return WIMLIB_ERR_INVALID_IMAGE;