From: Eric Biggers Date: Mon, 19 Oct 2015 00:39:34 +0000 (-0500) Subject: Forbid modifying multi-referenced images X-Git-Tag: v1.8.3~38 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=89698ed953532a5ccbeca5414cc10873aa33af71 Forbid modifying multi-referenced images --- diff --git a/include/wimlib.h b/include/wimlib.h index 93e44d75..cdc29889 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -2497,6 +2497,7 @@ enum wimlib_error_code { WIMLIB_ERR_UNABLE_TO_READ_CAPTURE_CONFIG = 83, WIMLIB_ERR_WIM_IS_INCOMPLETE = 84, WIMLIB_ERR_COMPACTION_NOT_POSSIBLE = 85, + WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES = 86, }; @@ -2715,12 +2716,17 @@ wimlib_delete_path(WIMStruct *wim, int image, * * Export an image, or all images, from a ::WIMStruct into another ::WIMStruct. * - * Note: after calling this function, the exported WIM image(s) cannot be - * independently modified because the image metadata will be shared between the - * two ::WIMStruct's. + * Specifically, if the destination ::WIMStruct contains n images, then + * the source image(s) will be appended, in order, starting at destination index + * n + 1. By default, all image metadata will be exported verbatim, + * but certain changes can be made by passing appropriate parameters. * - * Note: no changes are committed to disk until wimlib_write() or - * wimlib_overwrite() is called. + * wimlib_export_image() is only an in-memory operation; no changes are + * committed to disk until wimlib_write() or wimlib_overwrite() is called. + * + * A limitation of the current implementation of wimlib_export_image() is that + * the directory tree of a source or destination image cannot be updated + * following an export until one of the two images has been freed from memory. * * @param src_wim * The WIM from which to export the images, specified as a pointer to the @@ -3468,6 +3474,10 @@ wimlib_join_with_progress(const wimlib_tchar * const *swms, * Another process is currently modifying the WIM file. * @retval ::WIMLIB_ERR_FUSE * A non-zero status code was returned by @c fuse_main(). + * @retval ::WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES + * There are currently multiple references to the WIM image as a result of + * a call to wimlib_export_image(). Free one before attempting the + * read-write mount. * @retval ::WIMLIB_ERR_INVALID_IMAGE * @p image does not exist in @p wim. * @retval ::WIMLIB_ERR_INVALID_PARAM @@ -4351,6 +4361,9 @@ wimlib_unmount_image_with_progress(const wimlib_tchar *dir, * @retval ::WIMLIB_ERR_FVE_LOCKED_VOLUME * Windows-only: One of the "add" commands attempted to add files from an * encrypted BitLocker volume that hasn't yet been unlocked. + * @retval ::WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES + * There are currently multiple references to the WIM image as a result of + * a call to wimlib_export_image(). Free one before attempting the update. * @retval ::WIMLIB_ERR_INVALID_CAPTURE_CONFIG * The contents of a capture configuration file were invalid. * @retval ::WIMLIB_ERR_INVALID_IMAGE diff --git a/src/error.c b/src/error.c index 40d00a58..af212db0 100644 --- a/src/error.c +++ b/src/error.c @@ -337,6 +337,9 @@ static const tchar * const error_strings[] = { [WIMLIB_ERR_COMPACTION_NOT_POSSIBLE] = T("The WIM file cannot be compacted because of its format, " "its layout, or the write parameters specified by the user"), + [WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES] + = T("The WIM image cannot be modified because it is currently " + "referenced from multiple places"), }; WIMLIBAPI const tchar * diff --git a/src/mount_image.c b/src/mount_image.c index 239184aa..7750a4ee 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -2137,6 +2137,8 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir, } if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) { + if (imd->refcnt > 1) + return WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES; ret = lock_wim_for_append(wim); if (ret) return ret; diff --git a/src/update_image.c b/src/update_image.c index 49492a3f..66e5ed8d 100644 --- a/src/update_image.c +++ b/src/update_image.c @@ -1396,6 +1396,7 @@ wimlib_update_image(WIMStruct *wim, int update_flags) { int ret; + struct wim_image_metadata *imd; struct wimlib_update_command *cmds_copy; if (update_flags & ~WIMLIB_UPDATE_FLAG_SEND_PROGRESS) @@ -1404,7 +1405,14 @@ wimlib_update_image(WIMStruct *wim, /* Load the metadata for the image to modify (if not loaded already) */ ret = select_wim_image(wim, image); if (ret) - goto out; + return ret; + + imd = wim->image_metadata[image - 1]; + + /* Don't allow updating an image currently being shared by multiple + * WIMStructs (as a result of an export) */ + if (imd->refcnt > 1) + return WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES; /* Make a copy of the update commands, in the process doing certain * canonicalizations on paths (e.g. translating backslashes to forward @@ -1412,7 +1420,7 @@ wimlib_update_image(WIMStruct *wim, * commands. */ ret = copy_update_commands(cmds, num_cmds, &cmds_copy); if (ret) - goto out; + return ret; /* Perform additional checks on the update commands before we execute * them. */ @@ -1425,7 +1433,7 @@ wimlib_update_image(WIMStruct *wim, if (ret) goto out_free_cmds_copy; - mark_image_dirty(wim->image_metadata[image - 1]); + mark_image_dirty(imd); /* Statistics about the WIM image, such as the numbers of files and * directories, may have changed. Call xml_update_image_info() to @@ -1438,7 +1446,6 @@ wimlib_update_image(WIMStruct *wim, wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX; out_free_cmds_copy: free_update_commands(cmds_copy, num_cmds); -out: return ret; }