Add can_modify_wim(), can_delete_from_wim()
authorEric Biggers <ebiggers3@gmail.com>
Tue, 21 May 2013 19:42:37 +0000 (14:42 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 21 May 2013 19:42:37 +0000 (14:42 -0500)
include/wimlib.h
include/wimlib/wim.h
src/add_image.c
src/delete_image.c
src/export_image.c
src/mount_image.c
src/update_image.c
src/wim.c
src/xml.c

index 85b2f29..c1c00e4 100644 (file)
@@ -2275,8 +2275,7 @@ wimlib_resolve_image(WIMStruct *wim,
  *     @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.
+ *     @a wim is part of a split WIM.
  */
 extern int
 wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
@@ -2300,6 +2299,8 @@ wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @a description
  *     string.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim is part of a split WIM.
  */
 extern int
 wimlib_set_image_descripton(WIMStruct *wim, int image,
@@ -2324,6 +2325,8 @@ wimlib_set_image_descripton(WIMStruct *wim, int image,
  *     @a image does not specify a single existing image in @a wim.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @a flags string.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim is part of a split WIM.
  */
 extern int wimlib_set_image_flags(WIMStruct *wim, int image,
                                  const wimlib_tchar *flags);
@@ -2338,17 +2341,19 @@ extern int wimlib_set_image_flags(WIMStruct *wim, int image,
  * @param image
  *     The number of the image for which to change the name.
  * @param name
- *     The new name to give the image.  It must be a nonempty string.
+ *     New name to give the new image.  If @c NULL or empty, the new image is
+ *     given no name.  If nonempty, it must specify a name that does not
+ *     already exist in @a wim.
  *
  * @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.
  * @retval ::WIMLIB_ERR_INVALID_IMAGE
  *     @a image does not specify a single existing image in @a wim.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @a name string.
+ * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED
+ *     @a wim is part of a split WIM.
  */
 extern int wimlib_set_image_name(WIMStruct *wim, int image,
                                 const wimlib_tchar *name);
index 946eee1..c1e669f 100644 (file)
@@ -83,4 +83,10 @@ reopen_wim(WIMStruct *w);
 extern int
 close_wim(WIMStruct *w);
 
+extern int
+can_modify_wim(WIMStruct *wim);
+
+extern int
+can_delete_from_wim(WIMStruct *wim);
+
 #endif /* _WIMLIB_WIM_H */
index 7dcee10..d40dfa0 100644 (file)
@@ -80,11 +80,9 @@ wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
        if (name == NULL)
                name = T("");
 
-       if (wim->hdr.total_parts != 1) {
-               ERROR("Cannot add an image to a split WIM");
-               ret = WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       ret = can_modify_wim(wim);
+       if (ret)
                goto out;
-       }
 
        if (wimlib_image_name_in_use(wim, name)) {
                ERROR("There is already an image named \"%"TS"\" in the WIM!",
index 862fb66..e73efab 100644 (file)
  * Deletes an image from the WIM.
  */
 WIMLIBAPI int
-wimlib_delete_image(WIMStruct *w, int image)
+wimlib_delete_image(WIMStruct *wim, int image)
 {
        int ret;
        int first, last;
 
-       if (w->hdr.total_parts != 1) {
-               ERROR("Deleting an image from a split WIM is not supported.");
-               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
-       }
-
-       if (!w->all_images_verified) {
-               ret = wim_run_full_verifications(w);
-               if (ret)
-                       return ret;
-       }
+       ret = can_delete_from_wim(wim);
+       if (ret)
+               return ret;
 
        if (image == WIMLIB_ALL_IMAGES) {
-               last = w->hdr.image_count;
+               last = wim->hdr.image_count;
                first = 1;
        } else {
                last = image;
@@ -66,34 +59,34 @@ wimlib_delete_image(WIMStruct *w, int image)
                /* Even if the dentry tree is not allocated, we must select it (and
                 * therefore allocate it) so that we can decrement the reference counts
                 * in the lookup table.  */
-               ret = select_wim_image(w, image);
+               ret = select_wim_image(wim, image);
                if (ret)
                        return ret;
 
                /* Unless the image metadata is shared by another WIMStruct, free the
                 * dentry tree, any lookup table entries that have their refcnt
                 * decremented to 0, and the security data. */
-               put_image_metadata(w->image_metadata[image - 1], w->lookup_table);
+               put_image_metadata(wim->image_metadata[image - 1], wim->lookup_table);
 
                /* Get rid of the empty slot in the image metadata array. */
-               for (int i = image - 1; i < w->hdr.image_count - 1; i++)
-                       w->image_metadata[i] = w->image_metadata[i + 1];
+               for (int i = image - 1; i < wim->hdr.image_count - 1; i++)
+                       wim->image_metadata[i] = wim->image_metadata[i + 1];
 
                /* Decrement the image count. */
-               --w->hdr.image_count;
+               --wim->hdr.image_count;
 
                /* Fix the boot index. */
-               if (w->hdr.boot_idx == image)
-                       w->hdr.boot_idx = 0;
-               else if (w->hdr.boot_idx > image)
-                       w->hdr.boot_idx--;
+               if (wim->hdr.boot_idx == image)
+                       wim->hdr.boot_idx = 0;
+               else if (wim->hdr.boot_idx > image)
+                       wim->hdr.boot_idx--;
 
-               w->current_image = WIMLIB_NO_IMAGE;
+               wim->current_image = WIMLIB_NO_IMAGE;
 
                /* Remove the image from the XML information. */
-               xml_delete_image(&w->wim_info, image);
+               xml_delete_image(&wim->wim_info, image);
 
-               w->deletion_occurred = 1;
+               wim->deletion_occurred = 1;
        }
        return 0;
 }
index 455baa9..9f8bfa3 100644 (file)
@@ -114,11 +114,9 @@ wimlib_export_image(WIMStruct *src_wim,
        struct list_head lte_list_head;
        struct wim_inode *inode;
 
-       if (dest_wim->hdr.total_parts != 1) {
-               ERROR("Exporting an image to a split WIM is "
-                     "unsupported");
-               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
-       }
+       ret = can_modify_wim(dest_wim);
+       if (ret)
+               return ret;
 
        if (src_image == WIMLIB_ALL_IMAGES) {
                if (src_wim->hdr.image_count > 1) {
index f3e0a42..fbcc1ea 100644 (file)
@@ -2407,24 +2407,14 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        if (ret)
                goto out;
 
-       if ((mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) && (wim->hdr.total_parts != 1)) {
-               ERROR("Cannot mount a split WIM read-write");
-               ret = WIMLIB_ERR_SPLIT_UNSUPPORTED;
-               goto out;
-       }
-
-       if (num_additional_swms)
-               merge_lookup_tables(wim, additional_swms, num_additional_swms);
-
        if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
-               ret = wim_run_full_verifications(wim);
+               ret = can_delete_from_wim(wim);
                if (ret)
-                       goto out_restore_lookup_table;
+                       goto out;
        }
 
-       ret = wim_checksum_unhashed_streams(wim);
-       if (ret)
-               goto out_restore_lookup_table;
+       if (num_additional_swms)
+               merge_lookup_tables(wim, additional_swms, num_additional_swms);
 
        ret = select_wim_image(wim, image);
        if (ret)
index dd63854..f1776ec 100644 (file)
@@ -717,15 +717,21 @@ wimlib_update_image(WIMStruct *wim,
 {
        int ret;
        struct wimlib_update_command *cmds_copy;
+       bool deletion_requested = false;
 
        DEBUG("Updating image %d with %zu commands", image, num_cmds);
 
-       /* Refuse to update a split WIM. */
-       if (wim->hdr.total_parts != 1) {
-               ERROR("Cannot update a split WIM!");
-               ret = WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       for (size_t i = 0; i < num_cmds; i++)
+               if (cmds[i].op == WIMLIB_UPDATE_OP_DELETE)
+                       deletion_requested = true;
+
+       if (deletion_requested)
+               ret = can_delete_from_wim(wim);
+       else
+               ret = can_modify_wim(wim);
+
+       if (ret)
                goto out;
-       }
 
        /* Load the metadata for the image to modify (if not loaded already) */
        ret = select_wim_image(wim, image);
index 2907cd3..9e73c76 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -366,15 +366,16 @@ wimlib_print_files(WIMStruct *w, int image)
 
 /* Sets the index of the bootable image. */
 WIMLIBAPI int
-wimlib_set_boot_idx(WIMStruct *w, int boot_idx)
+wimlib_set_boot_idx(WIMStruct *wim, int boot_idx)
 {
-       if (w->hdr.total_parts != 1) {
-               ERROR("Cannot modify the boot index of a split WIM!");
-               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
-       }
-       if (boot_idx < 0 || boot_idx > w->hdr.image_count)
+       int ret;
+
+       ret = can_modify_wim(wim);
+       if (ret)
+               return ret;
+       if (boot_idx < 0 || boot_idx > wim->hdr.image_count)
                return WIMLIB_ERR_INVALID_IMAGE;
-       w->hdr.boot_idx = boot_idx;
+       wim->hdr.boot_idx = boot_idx;
        return 0;
 }
 
@@ -671,6 +672,30 @@ wim_checksum_unhashed_streams(WIMStruct *w)
        return 0;
 }
 
+int
+can_modify_wim(WIMStruct *wim)
+{
+       if (wim->hdr.total_parts != 1) {
+               if (wim->filename)
+                       ERROR("Cannot modify \"%"TS"\": is a split WIM!", wim->filename);
+               else
+                       ERROR("Cannot modify a split WIM!");
+               return WIMLIB_ERR_SPLIT_UNSUPPORTED;
+       }
+       return 0;
+}
+
+int
+can_delete_from_wim(WIMStruct *wim)
+{
+       int ret;
+
+       ret = can_modify_wim(wim);
+       if (ret == 0 && !wim->all_images_verified)
+               ret = wim_run_full_verifications(wim);
+       return ret;
+}
+
 /* Frees the memory for the WIMStruct, including all internal memory; also
  * closes all files associated with the WIMStruct.  */
 WIMLIBAPI void
index 67e0a22..6adba78 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -1542,13 +1542,16 @@ wimlib_set_image_name(WIMStruct *w, int image, const tchar *name)
 {
        tchar *p;
        int i;
+       int ret;
 
        DEBUG("Setting the name of image %d to %"TS, image, name);
 
-       if (!name || !*name) {
-               ERROR("Must specify a non-empty string for the image name");
-               return WIMLIB_ERR_INVALID_PARAM;
-       }
+       ret = can_modify_wim(w);
+       if (ret)
+               return ret;
+
+       if (name == NULL)
+               name = T("");
 
        if (image < 1 || image > w->hdr.image_count) {
                ERROR("%d is not a valid image", image);
@@ -1558,7 +1561,7 @@ wimlib_set_image_name(WIMStruct *w, int image, const tchar *name)
        for (i = 1; i <= w->hdr.image_count; i++) {
                if (i == image)
                        continue;
-               if (tstrcmp(w->wim_info->images[i - 1].name, name) == 0) {
+               if (!tstrcmp(w->wim_info->images[i - 1].name, name)) {
                        ERROR("The name \"%"TS"\" is already in use in the WIM!",
                              name);
                        return WIMLIB_ERR_IMAGE_NAME_COLLISION;
@@ -1580,6 +1583,11 @@ do_set_image_info_str(WIMStruct *w, int image, const tchar *tstr,
 {
        tchar *tstr_copy;
        tchar **dest_tstr_p;
+       int ret;
+
+       ret = can_modify_wim(w);
+       if (ret)
+               return ret;
 
        if (image < 1 || image > w->hdr.image_count) {
                ERROR("%d is not a valid image", image);