Implement soft delete
authorEric Biggers <ebiggers3@gmail.com>
Tue, 20 Nov 2012 07:15:36 +0000 (01:15 -0600)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 20 Nov 2012 07:15:36 +0000 (01:15 -0600)
doc/imagex-delete.1.in
programs/imagex.c
src/wim.c
src/wimlib.h
src/write.c

index 1d8c31760ae8705bfc16f04ba8bbcfafb0e1d2da..1505b9bd3e6d93b34f14202d50485fc500183d5b 100644 (file)
@@ -18,9 +18,10 @@ command to show what images a WIM file contains.
 
 .SH NOTES
 
-The WIM file is rebuilt with all unnecessary file data removed.  This is
-different from Microsoft's imagex.exe, which only will delete the directory tree
-metadata and XML data for this operation.
+By default, the WIM file is rebuilt with all unnecessary file data removed.
+This is different from Microsoft's imagex.exe, which only will delete the
+directory tree metadata and XML data for this operation.  (See the \fB--soft\fR
+option for the other kind of delete).
 
 Also, unlike imagex.exe, it is legal to delete all the images from a WIM and
 have a WIM with 0 images, although such a file wouldn't be very useful.
@@ -34,6 +35,17 @@ When reading \fIWIMFILE\fR, verify its integrity if the integrity table is
 present; additionally, when rewriting \fIWIMFILE\fR after the specified image was
 deleted, write an integrity table.  If this option is not specified, no integrity
 table is included in the new WIM file, even if there was one before.
+.TP 6
+\fB--soft\fR
+Perform a "soft delete".  Specifying this flag overrides the default behavior of
+rebuilding the entire WIM after deleting an image.  Instead, only minimal
+changes to correctly remove the image from the WIM will be taken.  In
+particular, all streams will be left alone, even if they are no longer
+referenced.  This is probably not what you want, because almost no space will be
+saved by deleting an image in this way.
+
+You may use \fBimagex optimize\fR to delete unreferenced streams from a WIM that
+has had images soft-deleted from it.
 
 .SH EXAMPLES
 Delete the first image from 'boot.wim':
index 4e5765f649b2b650da84dfd1b47fd0b9ad199dd2..d047130b20b395983283ce21b5619448954734da 100644 (file)
@@ -77,7 +77,7 @@ static const char *usage_strings[] = {
 "                      [--flags EDITION_ID] [--verbose] [--dereference]\n"
 "                      [--config=FILE] [--threads=NUM_THREADS]\n",
 [DELETE] =
-"imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check]\n",
+"imagex delete WIMFILE (IMAGE_NUM | IMAGE_NAME | all) [--check] [--soft]\n",
 [DIR] =
 "imagex dir WIMFILE (IMAGE_NUM | IMAGE_NAME | all)\n",
 [EXPORT] =
@@ -134,6 +134,7 @@ static const struct option capture_or_append_options[] = {
 };
 static const struct option delete_options[] = {
        {"check", no_argument, NULL, 'c'},
+       {"soft",  no_argument, NULL, 's'},
        {NULL, 0, NULL, 0},
 };
 
@@ -675,6 +676,9 @@ static int imagex_delete(int argc, const char **argv)
                        open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
                        write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
                        break;
+               case 's':
+                       write_flags |= WIMLIB_WRITE_FLAG_SOFT_DELETE;
+                       break;
                default:
                        usage(DELETE);
                        return -1;
index 0507e477eec45696fbae381e33485a75ef730199..f40915fde0cbb2e2f4eaff4a42d8a80fb0b2a7fb 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -132,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 {
index 6c99ffdbda1128e848d18a4f9dfd6dbb15a330e9..ce079ce477d499f8ea1d5ee321ecb7b51e11a683 100644 (file)
@@ -284,6 +284,15 @@ enum wim_compression_type {
  * same.  Instead, recompress them. */
 #define WIMLIB_WRITE_FLAG_RECOMPRESS           0x00000020
 
+/** Specifying this flag overrides the default behavior of wimlib_overwrite()
+ * after one or more calls to wimlib_delete_image(), which is to rebuild the
+ * entire WIM.  If you specifiy this flag to wimlib_overwrite() instead, only
+ * minimal changes to correctly remove the image from the WIM will be taken.  In
+ * particular, all streams will be left alone, even if they are no longer
+ * references.  This is probably not what you want, because almost no space will
+ * be spaced by deleting an image in this way. */
+#define WIMLIB_WRITE_FLAG_SOFT_DELETE          0x00000040
+
 /** Mark the image being added as the bootable image of the WIM. */
 #define WIMLIB_ADD_IMAGE_FLAG_BOOT             0x00000001
 
@@ -1143,8 +1152,9 @@ extern int wimlib_overwrite(WIMStruct *wim, int write_flags,
                            unsigned num_threads);
 
 /**
- * This function is deprecated; call wimlib_overwrite() without the
- * WIMLIB_WRITE_FLAG_REBUILD flag instead.
+ * This function is deprecated; call wimlib_overwrite() instead.
+ * (wimlib_overwrite() no longer rebuilds the full WIM unless it has to or is
+ * specified explicitly with ::WIMLIB_WRITE_FLAG_REBUILD)
  */
 extern int wimlib_overwrite_xml_and_header(WIMStruct *wim, int write_flags);
 
index a9cb6aecaa6c6da0db11b159014e192ad29fac67..1eb695d5edca2dbd03a1404e3c7e3b6585f0a0e2 100644 (file)
@@ -1570,6 +1570,8 @@ WIMLIBAPI int wimlib_write(WIMStruct *w, const char *path,
        if (!w || !path)
                return WIMLIB_ERR_INVALID_PARAM;
 
+       write_flags &= WIMLIB_WRITE_MASK_PUBLIC;
+
        if (image != WIM_ALL_IMAGES &&
             (image < 1 || image > w->hdr.image_count))
                return WIMLIB_ERR_INVALID_IMAGE;
@@ -1746,9 +1748,9 @@ static int overwrite_wim_inplace(WIMStruct *w, int write_flags,
        if (ret != 0)
                return ret;
 
-       if (modified_image_idx == w->hdr.image_count) {
-               /* If no images are modified, a new lookup table does not need
-                * to be written. */
+       if (modified_image_idx == w->hdr.image_count && !w->deletion_occurred) {
+               /* If no images have been modified and no images have been
+                * deleted, a new lookup table does not need to be written. */
                wimlib_assert(list_empty(&stream_list));
                old_wim_end = w->hdr.lookup_table_res_entry.offset +
                              w->hdr.lookup_table_res_entry.size;
@@ -1877,7 +1879,9 @@ WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags,
                return WIMLIB_ERR_SPLIT_UNSUPPORTED;
        }
 
-       if (!w->deletion_occurred && !(write_flags & WIMLIB_WRITE_FLAG_REBUILD)) {
+       if ((!w->deletion_occurred || (write_flags & WIMLIB_WRITE_FLAG_SOFT_DELETE))
+           && !(write_flags & WIMLIB_WRITE_FLAG_REBUILD))
+       {
                int i, modified_image_idx;
                for (i = 0; i < w->hdr.image_count && !w->image_metadata[i].modified; i++)
                        ;