--hardlink fix
authorEric Biggers <ebiggers3@gmail.com>
Mon, 20 Aug 2012 02:45:41 +0000 (21:45 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Mon, 20 Aug 2012 02:45:41 +0000 (21:45 -0500)
51 files changed:
src/dentry.c
src/extract.c
src/lookup_table.c
src/symlink.c
tests/dir/comp.c [deleted symlink]
tests/dir/comp.h [deleted symlink]
tests/dir/decomp.c [deleted symlink]
tests/dir/decomp.h [deleted symlink]
tests/dir/dentry.c [deleted symlink]
tests/dir/dentry.h [deleted symlink]
tests/dir/endianness.h [deleted symlink]
tests/dir/extract.c [deleted symlink]
tests/dir/header.c [deleted symlink]
tests/dir/integrity.c [deleted symlink]
tests/dir/io.h [deleted symlink]
tests/dir/join.c [deleted symlink]
tests/dir/lookup_table.c [deleted symlink]
tests/dir/lookup_table.h [deleted symlink]
tests/dir/lz.c [deleted symlink]
tests/dir/lzx-common.c [deleted symlink]
tests/dir/lzx-comp.c [deleted symlink]
tests/dir/lzx-decomp.c [deleted symlink]
tests/dir/lzx.h [deleted symlink]
tests/dir/modify.c [deleted symlink]
tests/dir/mount.c [deleted symlink]
tests/dir/resource.c [deleted symlink]
tests/dir/security.c [deleted symlink]
tests/dir/security.h [deleted symlink]
tests/dir/sha1.c [deleted symlink]
tests/dir/sha1.h [deleted symlink]
tests/dir/split.c [deleted symlink]
tests/dir/subdir/empty_file [deleted file]
tests/dir/subdir/identical_file1 [deleted file]
tests/dir/subdir/identical_file2 [deleted file]
tests/dir/subdir/short_file [deleted file]
tests/dir/subdir/zeroes [deleted file]
tests/dir/timestamp.h [deleted symlink]
tests/dir/util.c [deleted symlink]
tests/dir/util.h [deleted symlink]
tests/dir/wim.c [deleted symlink]
tests/dir/wimlib.h [deleted symlink]
tests/dir/wimlib_internal.h [deleted symlink]
tests/dir/write.c [deleted symlink]
tests/dir/xml.c [deleted symlink]
tests/dir/xml.h [deleted symlink]
tests/dir/xpress-comp.c [deleted symlink]
tests/dir/xpress-decomp.c [deleted symlink]
tests/dir/xpress.h [deleted symlink]
tests/dir2/imagex.c [deleted symlink]
tests/dir2/mkwinpeimg [deleted symlink]
tests/test-imagex

index 0e3d977..35c17a4 100644 (file)
@@ -36,6 +36,7 @@
 #include "timestamp.h"
 #include "lookup_table.h"
 #include "sha1.h"
+#include <errno.h>
 #include <unistd.h>
 #include <sys/stat.h>
 
index 0cb06b8..1648ade 100644 (file)
@@ -47,7 +47,7 @@ static int extract_regular_file_linked(const struct dentry *dentry,
                                       const char *output_dir,
                                       const char *output_path,
                                       int extract_flags,
-                                      const struct lookup_table_entry *lte)
+                                      struct lookup_table_entry *lte)
 {
        /* This mode overrides the normal hard-link extraction and
         * instead either symlinks or hardlinks *all* identical files in
@@ -56,6 +56,7 @@ static int extract_regular_file_linked(const struct dentry *dentry,
 
        wimlib_assert(lte->file_on_disk);
 
+
        if (extract_flags & WIMLIB_EXTRACT_FLAG_HARDLINK) {
                if (link(lte->file_on_disk, output_path) != 0) {
                        ERROR_WITH_ERRNO("Failed to hard link "
@@ -71,6 +72,8 @@ static int extract_regular_file_linked(const struct dentry *dentry,
                const char *p2;
                size_t i;
 
+               wimlib_assert(extract_flags & WIMLIB_EXTRACT_FLAG_SYMLINK);
+
                num_path_components = 
                        get_num_path_components(dentry->full_path_utf8) - 1;
                num_output_dir_path_components =
@@ -208,14 +211,19 @@ static int extract_regular_file(WIMStruct *w,
 
        lte = __lookup_resource(w->lookup_table, dentry_hash(dentry));
 
-       if ((extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) &&
-             lte && lte->out_refcnt != 0)
-               return extract_regular_file_linked(dentry, output_dir,
-                                                  output_path, extract_flags,
-                                                  lte);
-       else
-               return extract_regular_file_unlinked(w, dentry, output_path,
-                                                    extract_flags, lte);
+       if ((extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK |
+                             WIMLIB_EXTRACT_FLAG_HARDLINK)) && lte) {
+               if (lte->out_refcnt++ != 0)
+                       return extract_regular_file_linked(dentry, output_dir,
+                                                          output_path,
+                                                          extract_flags, lte);
+               lte->file_on_disk = STRDUP(output_path);
+               if (!lte->file_on_disk)
+                       return WIMLIB_ERR_NOMEM;
+       }
+
+       return extract_regular_file_unlinked(w, dentry, output_path,
+                                            extract_flags, lte);
 
 }
 
index 6ad8872..bb6e2b5 100644 (file)
@@ -27,6 +27,7 @@
 #include "wimlib_internal.h"
 #include "lookup_table.h"
 #include "io.h"
+#include <errno.h>
 
 struct lookup_table *new_lookup_table(size_t capacity)
 {
index e7d7be9..e7163e5 100644 (file)
@@ -2,6 +2,7 @@
 #include "io.h"
 #include "lookup_table.h"
 #include "sha1.h"
+#include <errno.h>
 
 /*
  * Find the symlink target of a symbolic link or junction point in the WIM.
diff --git a/tests/dir/comp.c b/tests/dir/comp.c
deleted file mode 120000 (symlink)
index 1678379..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/comp.c
\ No newline at end of file
diff --git a/tests/dir/comp.h b/tests/dir/comp.h
deleted file mode 120000 (symlink)
index b259940..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/comp.h
\ No newline at end of file
diff --git a/tests/dir/decomp.c b/tests/dir/decomp.c
deleted file mode 120000 (symlink)
index cc67a22..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/decomp.c
\ No newline at end of file
diff --git a/tests/dir/decomp.h b/tests/dir/decomp.h
deleted file mode 120000 (symlink)
index 22a2226..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/decomp.h
\ No newline at end of file
diff --git a/tests/dir/dentry.c b/tests/dir/dentry.c
deleted file mode 120000 (symlink)
index d864209..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/dentry.c
\ No newline at end of file
diff --git a/tests/dir/dentry.h b/tests/dir/dentry.h
deleted file mode 120000 (symlink)
index 10cc735..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/dentry.h
\ No newline at end of file
diff --git a/tests/dir/endianness.h b/tests/dir/endianness.h
deleted file mode 120000 (symlink)
index 48fd8d3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/endianness.h
\ No newline at end of file
diff --git a/tests/dir/extract.c b/tests/dir/extract.c
deleted file mode 120000 (symlink)
index 44480bc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/extract.c
\ No newline at end of file
diff --git a/tests/dir/header.c b/tests/dir/header.c
deleted file mode 120000 (symlink)
index 0a3f05e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/header.c
\ No newline at end of file
diff --git a/tests/dir/integrity.c b/tests/dir/integrity.c
deleted file mode 120000 (symlink)
index 997d473..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/integrity.c
\ No newline at end of file
diff --git a/tests/dir/io.h b/tests/dir/io.h
deleted file mode 120000 (symlink)
index 32882db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/io.h
\ No newline at end of file
diff --git a/tests/dir/join.c b/tests/dir/join.c
deleted file mode 120000 (symlink)
index dcffc6c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/join.c
\ No newline at end of file
diff --git a/tests/dir/lookup_table.c b/tests/dir/lookup_table.c
deleted file mode 120000 (symlink)
index a685a89..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/lookup_table.c
\ No newline at end of file
diff --git a/tests/dir/lookup_table.h b/tests/dir/lookup_table.h
deleted file mode 120000 (symlink)
index fd64815..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/lookup_table.h
\ No newline at end of file
diff --git a/tests/dir/lz.c b/tests/dir/lz.c
deleted file mode 120000 (symlink)
index 0a3c850..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/lz.c
\ No newline at end of file
diff --git a/tests/dir/lzx-common.c b/tests/dir/lzx-common.c
deleted file mode 120000 (symlink)
index cd78231..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/lzx-common.c
\ No newline at end of file
diff --git a/tests/dir/lzx-comp.c b/tests/dir/lzx-comp.c
deleted file mode 120000 (symlink)
index a0c4e9e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/lzx-comp.c
\ No newline at end of file
diff --git a/tests/dir/lzx-decomp.c b/tests/dir/lzx-decomp.c
deleted file mode 120000 (symlink)
index 2235acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/lzx-decomp.c
\ No newline at end of file
diff --git a/tests/dir/lzx.h b/tests/dir/lzx.h
deleted file mode 120000 (symlink)
index 2b55c6b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/lzx.h
\ No newline at end of file
diff --git a/tests/dir/modify.c b/tests/dir/modify.c
deleted file mode 120000 (symlink)
index 007b89e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/modify.c
\ No newline at end of file
diff --git a/tests/dir/mount.c b/tests/dir/mount.c
deleted file mode 120000 (symlink)
index d1ee2fc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/mount.c
\ No newline at end of file
diff --git a/tests/dir/resource.c b/tests/dir/resource.c
deleted file mode 120000 (symlink)
index 02de13c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/resource.c
\ No newline at end of file
diff --git a/tests/dir/security.c b/tests/dir/security.c
deleted file mode 120000 (symlink)
index 55e2465..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/security.c
\ No newline at end of file
diff --git a/tests/dir/security.h b/tests/dir/security.h
deleted file mode 120000 (symlink)
index fa9a3d7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/security.h
\ No newline at end of file
diff --git a/tests/dir/sha1.c b/tests/dir/sha1.c
deleted file mode 120000 (symlink)
index bf0a00b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/sha1.c
\ No newline at end of file
diff --git a/tests/dir/sha1.h b/tests/dir/sha1.h
deleted file mode 120000 (symlink)
index 4902ee8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/sha1.h
\ No newline at end of file
diff --git a/tests/dir/split.c b/tests/dir/split.c
deleted file mode 120000 (symlink)
index c8b6759..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/split.c
\ No newline at end of file
diff --git a/tests/dir/subdir/empty_file b/tests/dir/subdir/empty_file
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tests/dir/subdir/identical_file1 b/tests/dir/subdir/identical_file1
deleted file mode 100644 (file)
index ce01362..0000000
+++ /dev/null
@@ -1 +0,0 @@
-hello
diff --git a/tests/dir/subdir/identical_file2 b/tests/dir/subdir/identical_file2
deleted file mode 100644 (file)
index ce01362..0000000
+++ /dev/null
@@ -1 +0,0 @@
-hello
diff --git a/tests/dir/subdir/short_file b/tests/dir/subdir/short_file
deleted file mode 100644 (file)
index 56a6051..0000000
+++ /dev/null
@@ -1 +0,0 @@
-1
\ No newline at end of file
diff --git a/tests/dir/subdir/zeroes b/tests/dir/subdir/zeroes
deleted file mode 100644 (file)
index a64a5a9..0000000
Binary files a/tests/dir/subdir/zeroes and /dev/null differ
diff --git a/tests/dir/timestamp.h b/tests/dir/timestamp.h
deleted file mode 120000 (symlink)
index 499c216..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/timestamp.h
\ No newline at end of file
diff --git a/tests/dir/util.c b/tests/dir/util.c
deleted file mode 120000 (symlink)
index 87f5cc3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/util.c
\ No newline at end of file
diff --git a/tests/dir/util.h b/tests/dir/util.h
deleted file mode 120000 (symlink)
index 82c8f13..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/util.h
\ No newline at end of file
diff --git a/tests/dir/wim.c b/tests/dir/wim.c
deleted file mode 120000 (symlink)
index 742ee97..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/wim.c
\ No newline at end of file
diff --git a/tests/dir/wimlib.h b/tests/dir/wimlib.h
deleted file mode 120000 (symlink)
index 50fea46..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/wimlib.h
\ No newline at end of file
diff --git a/tests/dir/wimlib_internal.h b/tests/dir/wimlib_internal.h
deleted file mode 120000 (symlink)
index d8b284f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/wimlib_internal.h
\ No newline at end of file
diff --git a/tests/dir/write.c b/tests/dir/write.c
deleted file mode 120000 (symlink)
index b7406c5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/write.c
\ No newline at end of file
diff --git a/tests/dir/xml.c b/tests/dir/xml.c
deleted file mode 120000 (symlink)
index b8a30e8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/xml.c
\ No newline at end of file
diff --git a/tests/dir/xml.h b/tests/dir/xml.h
deleted file mode 120000 (symlink)
index 240aa39..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/xml.h
\ No newline at end of file
diff --git a/tests/dir/xpress-comp.c b/tests/dir/xpress-comp.c
deleted file mode 120000 (symlink)
index 2027648..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/xpress-comp.c
\ No newline at end of file
diff --git a/tests/dir/xpress-decomp.c b/tests/dir/xpress-decomp.c
deleted file mode 120000 (symlink)
index 3a60d8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/xpress-decomp.c
\ No newline at end of file
diff --git a/tests/dir/xpress.h b/tests/dir/xpress.h
deleted file mode 120000 (symlink)
index 14c0399..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../src/xpress.h
\ No newline at end of file
diff --git a/tests/dir2/imagex.c b/tests/dir2/imagex.c
deleted file mode 120000 (symlink)
index 9da744b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../programs/imagex.c
\ No newline at end of file
diff --git a/tests/dir2/mkwinpeimg b/tests/dir2/mkwinpeimg
deleted file mode 120000 (symlink)
index 80b4805..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../programs/mkwinpeimg
\ No newline at end of file
index 99f4423..3f33a2f 100755 (executable)
@@ -29,175 +29,356 @@ imagex() {
        #/usr/bin/env cmp $@
 #}
 
-
 cleanup() {
        if [ -d tmp ] && mountpoint tmp > /dev/null; then
                fusermount -u tmp > /dev/null;
        fi
-       rm -rf tmp* *.wim *.swm dir3
+       rm -rf dir* tmp* *.wim *.swm
 }
 trap cleanup exit
 
-# Capturing and applying WIM with None, LZX, and XPRESS compression
+# Make test directory
+mkdir dir
+cp ../src/*.c ../src/*.h dir
+mkdir dir/subdir
+echo 'hello' > dir/subdir/hello
+echo 'hello' > dir/subdir/hello2
+ln dir/subdir/hello dir/subdir/hellolink
+echo -n > dir/subdir/empty_file
+ln -s hello dir/subdir/rel_symlink
 
-echo "Testing capture and application of uncompressed WIM"
-imagex capture dir dir.wim
-imagex apply dir.wim tmp
-test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "None";
-diff -q -r dir tmp
-rm -rf dir.wim tmp
+mkdir dir2
+echo 'testing' > dir2/file
+dd if=/dev/zero of=dir2/zeroes bs=4096 count=5
 
-echo "Testing capture and application of LZX-compressed WIM"
-imagex capture dir dir.wim --compress=maximum
-imagex apply dir.wim tmp
-test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "LZX";
-diff -q -r dir tmp
-rm -rf dir.wim tmp
+error() {
+       echo "**********************************************"
+       echo "                  Test failure                "
+       echo $*
+       echo "**********************************************"
+       exit 1
+}
 
-echo "Testing capture and application of XPRESS-compressed WIM"
-imagex capture dir dir.wim --compress=fast
-imagex apply dir.wim tmp
-test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "XPRESS";
-diff -q -r dir tmp
-rm -rf dir.wim tmp
+# Capturing and applying WIM with None, LZX, and XPRESS compression
+
+for comp_type in None LZX XPRESS; do
+       echo "Testing capture and application of $comp_type-compressed WIM"
+       if ! imagex capture dir dir.wim --compress=$comp_type; then
+               error "'imagex capture' failed"
+       fi
+       if ! imagex apply dir.wim tmp; then
+               error "'imagex apply' failed"
+       fi
+       if ! test "`imagex info dir.wim | grep Compression | awk '{print $2}'`" = "$comp_type"; then
+               error "'imagex info' didn't report the compression type correctly"
+       fi
+       if ! diff -q -r dir tmp; then
+               error "Recursive diff of extracted directory with original failed"
+       fi
+       if ! test `stat -c %h tmp/subdir/hello` = 2; then
+               error "Incorrect number of hard links in extracted file"
+       fi
+       if ! test `stat -c %i tmp/subdir/hello` != `stat -c %i tmp/subdir/hello2`; then
+               error "Expected different inode numbers in files not hard-linked"
+       fi
+       if ! test "`stat -c %i tmp/subdir/hello`" = "`stat -c %i tmp/subdir/hellolink`"; then
+               error "Expected same inode numbers in hard-linked files"
+       fi
+       if ! test -L tmp/subdir/rel_symlink; then
+               error "Symlink not extracted correctly"
+       fi
+       if ! test "`readlink tmp/subdir/rel_symlink`" = "hello"; then
+               error "Symlink target not correct"
+       fi
+       
+       rm -rf dir.wim tmp
+done
 
 # Capturing and modifying name, description, and bootable flag
 
 echo "Testing capture of WIM with default name and description"
 imagex capture dir dir.wim
-test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "dir";
-test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = "";
-rm -rf dir.wim tmp
+if ! test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "dir"; then
+       error "WIM name not set correctly"
+fi
+if ! test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = ""; then
+       error "WIM description not set correctly"
+fi
 
 echo "Testing capture of WIM with default boot flag"
 imagex capture dir dir.wim
-test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0";
+if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
+       error "WIM boot flag not set correctly"
+fi
+
 echo "Testing changing image bootable flag"
-imagex info dir.wim 1 --boot
-test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1";
+if ! imagex info dir.wim 1 --boot; then
+       error "Failed to change bootable image"
+fi
+if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
+       error "Bootable image not changed correctly"
+fi
 echo "Testing changing image bootable flag"
-imagex info dir.wim 0 --boot
-test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0";
+if ! imagex info dir.wim 0 --boot; then
+       error "Failed to reset bootable image"
+fi
+if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
+       error "Bootable image not reset correctly"
+fi
 echo "Testing changing image bootable flag to invalid image (this should generate errors)"
-! imagex info dir.wim 2 --boot 
-test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0";
+if imagex info dir.wim 2 --boot; then
+       error "Succeeded in changing bootable image to invalid number"
+fi
+if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
+       error "Boot flag was changed even though the change command was supposed to fail"
+fi
 rm -rf dir.wim tmp
 
 echo "Testing capture of WIM with name and description"
-imagex capture dir dir.wim "myname" "mydesc"
-test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "myname";
-test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = "mydesc";
+if ! imagex capture dir dir.wim "myname" "mydesc"; then
+       error "Failed to capture WIM with specified name and description"
+fi
+if ! test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "myname"; then
+       error "WIM name not set correctly"
+fi
+if ! test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = "mydesc"; then
+       error "WIM name not set correctly"
+fi
 echo "Testing printing WIM lookup table"
-imagex info --lookup-table dir.wim
+if ! imagex info --lookup-table dir.wim > /dev/null; then
+       error "Failed to print WIM lookup table"
+fi
 echo "Testing printing WIM header"
-imagex info --header dir.wim
+if ! imagex info --header dir.wim > /dev/null; then
+       error "Failed to print WIM header"
+fi
 echo "Testing printing WIM XML info"
-imagex info --xml dir.wim
+if ! imagex info --xml dir.wim > /dev/null; then
+       error "Failed to print WIM XML data"
+fi
 echo "Testing extracting WIM XML info"
-imagex info --extract-xml=dir.xml dir.wim
+if ! imagex info --extract-xml=dir.xml dir.wim; then
+       error "Failed to extract WIM XML data"
+fi
 echo "Testing printing WIM metadata"
-imagex info --metadata dir.wim
+if ! imagex info --metadata dir.wim > /dev/null; then
+       error "Failed to print WIM metadata"
+fi
 rm -rf dir.wim tmp dir.xml
 
 echo "Testing capture of bootable WIM"
-imagex capture dir dir.wim --boot
-test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1";
+if ! imagex capture dir dir.wim --boot; then
+       error "Failed to capture bootable WIM"
+fi
+if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
+       error "Boot flag on bootable WIM not set correctly"
+fi
 rm -rf dir.wim tmp
 
 # Integrity table
 
 echo "Testing capture of WIM with integrity table"
-imagex capture dir dir.wim --check
-test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
-imagex apply --check dir.wim tmp
-diff -q -r dir tmp
+if ! imagex capture dir dir.wim --check; then
+       error "Failed to capture WIM with integrity table"
+fi
+if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then
+       error "Integrity table on WIM not made"
+fi
+if ! imagex apply --check dir.wim tmp; then
+       error "Integrity table on WIM not made correctly"
+fi
+if ! diff -q -r dir tmp; then
+       error "Recursive diff of applied WIM with original directory failed"
+fi
 rm -rf dir.wim tmp
 
 # Appending and deleting images
 
 echo "Testing appending WIM image"
 imagex capture dir dir.wim
-imagex append dir2 dir.wim
-test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 2;
+if ! imagex append dir2 dir.wim; then
+       error "Appending WIM image failed"
+fi
+if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 2; then
+       error "WIM image count not correct"
+fi
+
 echo "Testing appending WIM image with existing name (this should generate errors)"
-! imagex append dir2 dir.wim
+if imagex append dir2 dir.wim; then
+       error "Adding duplicate image name didn't fail"
+fi
 echo "Testing appending WIM image with new name"
-imagex append dir2 dir.wim "newname"
+if ! imagex append dir2 dir.wim "newname"; then
+       error "Appending WIM image failed"
+fi
 echo "Testing appending WIM image with integrity check"
-imagex append dir2 dir.wim "newname2" --check
-test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
+if ! imagex append dir2 dir.wim "newname2" --check; then
+       error "Appending WIM image failed"
+fi
+if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then
+       error "Integrity table not set correctly on image append"
+fi
 echo "Testing appending WIM image with no integrity check"
-imagex append dir2 dir.wim "newname3"
-test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "no";
-test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 5;
+if ! imagex append dir2 dir.wim "newname3"; then
+       error "Appending WIM image failed"
+fi
+if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "no"; then
+       error "WIM integrity table not removed"
+fi
+# 5 images at this point
+if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 5; then
+       error "WIM does not contain the expected 5 images"
+fi
 echo "Testing deleting first WIM image"
-imagex delete dir.wim 1
-test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 4;
+if ! imagex delete dir.wim 1; then
+       error "Failed to delete WIM image"
+fi
+if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 4; then
+       error "WIM image not deleted correctly"
+fi
 echo "Testing deleting last WIM image"
-imagex delete dir.wim 4
-test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3;
+if ! imagex delete dir.wim 4; then
+       error "Failed to delete WIM image"
+fi
+if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then
+       error "WIM image not deleted correctly"
+fi
 echo "Testing deleting invalid WIM image (this should generate errors)"
-! imagex delete dir.wim 4
-test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3;
+if imagex delete dir.wim 4; then
+       error "Expected to fail to delete non-existent WIM image"
+fi
+if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 3; then
+       error "Image count changed even though we intentionally failed to delete an image"
+fi
 echo "Testing deleting all WIM images"
-imagex delete dir.wim all
-test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 0;
+if ! imagex delete dir.wim all; then
+       error "Failed to delete all images from WIM"
+fi
+if ! test "`imagex info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 0; then
+       error "Couldn't delete all WIM images correctly"
+fi
 echo "Testing appending directory to empty WIM and making it bootable"
-imagex append dir dir.wim "myname" "mydesc" --check --boot
-test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
-test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1";
+if ! imagex append dir dir.wim "myname" "mydesc" --check --boot; then
+       error "Couldn't append named, described, bootable image to empty WIM with integrity check"
+fi
+if ! test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then
+       error "Integrity check not found"
+fi
+if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
+       error "Bootable image not set correctly"
+fi
 echo "Testing appending non-directory (should generate errors)"
-! imagex append dir.wim dir.wim
+if imagex append dir.wim dir.wim; then
+       error "Incorrectly succeeded to append non-directory to WIM"
+fi
 echo "Testing appending non-existent file (should generate errors)"
-! imagex append SOME_NONEXISTENT_FILE dir.wim
+if imagex append SOME_NONEXISTENT_FILE dir.wim; then
+       error "Incorrectly succeeded to append non-existent file to WIM"
+fi
 echo "Testing appending directory containing unreadable file (should generate errors)"
 mkdir -p dir3
 touch dir3/file
 chmod -r dir3/file
-! imagex append dir3 dir.wim
+if imagex append dir3 dir.wim; then
+       error "Incorrectly succeeded in capturing directory with unreadable file"
+fi
 rm -rf dir3 dir.wim
 
 # Applying multiple images, applying with hardlinks/symlinks
 
-imagex capture dir dir.wim
-imagex append dir dir.wim "myname"
 echo "Testing application of multiple images"
-imagex apply dir.wim all tmp
-diff -q -r tmp/dir tmp/myname
-test `stat -c %h tmp/dir/lz.c` = 1;
-test `stat -c %h tmp/myname/lz.c` = 1;
-test `stat -c %i tmp/myname/lz.c` != `stat -c %i tmp/dir/lz.c`;
+if ! imagex capture dir dir.wim; then
+       error "Failed to prepare test WIM"
+fi
+if ! imagex append dir dir.wim "myname"; then
+       error "Failed to append image to test WIM"
+fi
+if ! imagex apply dir.wim all tmp; then
+       error "Applying multiple images failed"
+fi
+if ! diff -q -r tmp/dir tmp/myname || ! diff -q -r dir tmp/dir; then
+       error "Recursive diff of applied WIM with original directory failed"
+fi
+if test "`stat -c %h tmp/dir/lz.c`" != 1; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %h tmp/myname/lz.c`" != 1; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %i tmp/myname/lz.c`" = "`stat -c %i tmp/dir/lz.c`"; then
+       error "Incorrect inode number"
+fi
 rm -rf tmp
 echo "Testing application of multiple images with hardlinks"
-imagex apply dir.wim all tmp --hardlink
-diff -q -r tmp/dir tmp/myname
-test `stat -c %h tmp/dir/lz.c` = 2;
-test `stat -c %h tmp/myname/lz.c` = 2;
-test `stat -c %i tmp/myname/lz.c` = `stat -c %i tmp/dir/lz.c`;
+if ! imagex apply dir.wim all tmp --hardlink; then
+       error "Failed to apply multiple images with cross-image hardlinks"
+fi
+if ! diff -q -r tmp/dir tmp/myname || ! diff -q -r dir tmp/dir; then
+       error "Recursive diff of applied WIM with original directory failed"
+fi
+if test "`stat -c %h tmp/dir/lz.c`" != 2; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %h tmp/myname/lz.c`" != 2; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %i tmp/myname/lz.c`" != "`stat -c %i tmp/dir/lz.c`"; then
+       error "Incorrect inode number"
+fi
 rm -rf tmp
+
 echo "Testing application of single image containing identical files"
-imagex apply dir.wim 1 tmp
-test `stat -c %h tmp/subdir/identical_file1` = 1;
-test `stat -c %h tmp/subdir/identical_file2` = 1;
-test `stat -c %i tmp/subdir/identical_file1` != `stat -c %i tmp/subdir/identical_file2`;
-! readlink tmp/subdir/identical_file1 && ! readlink tmp/subdir/identical_file2
+if ! imagex apply dir.wim 1 tmp; then
+       error "Failed to apply WIM"
+fi
+if test "`stat -c %h tmp/subdir/hello`" != 2; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %h tmp/subdir/hello2`" != 1; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %i tmp/subdir/hello`" = "`stat -c %i tmp/subdir/hello2`"; then
+       error "Inode numbers on non-hard-linked files are the same"
+fi
+if test "`stat -c %i tmp/subdir/hello`" != "`stat -c %i tmp/subdir/hellolink`"; then
+       error "Inode numbers on hard-linked files are different"
+fi
 rm -rf tmp
 
 echo "Testing application of single image containing identical files with hardlinks"
-imagex apply dir.wim 1 tmp --hardlink
-test `stat -c %h tmp/subdir/identical_file1` = 2;
-test `stat -c %h tmp/subdir/identical_file2` = 2;
-test `stat -c %i tmp/subdir/identical_file1` = `stat -c %i tmp/subdir/identical_file2`;
-! readlink tmp/subdir/identical_file1 && ! readlink tmp/subdir/identical_file2
+if ! imagex apply dir.wim 1 tmp --hardlink; then
+       error "Failed to apply WIM"
+fi
+if test "`stat -c %h tmp/subdir/hello`" != 3; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %h tmp/subdir/hello2`" != 3; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %i tmp/subdir/hello`" != "`stat -c %i tmp/subdir/hello2`"; then
+       error "Hard link set does not share inode number"
+fi
+if test "`stat -c %i tmp/subdir/hello`" != "`stat -c %i tmp/subdir/hellolink`"; then
+       error "Hard link set does not share inode number"
+fi
 rm -rf tmp
 
 echo "Testing application of single image containing identical files with symlinks"
-imagex apply dir.wim 1 tmp --symlink
-test `stat -c %h tmp/subdir/identical_file1` = 1;
-test `stat -c %h tmp/subdir/identical_file2` = 1;
-test `stat -c %i tmp/subdir/identical_file1` != `stat -c %i tmp/subdir/identical_file2`;
-readlink tmp/subdir/identical_file1 > /dev/null || \
-               readlink tmp/subdir/identical_file2 > /dev/null
+if ! imagex apply dir.wim 1 tmp --symlink; then
+       error "Failed to apply WIM"
+fi
+if test "`stat -c %h tmp/subdir/hello`" != 1; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %h tmp/subdir/hello2`" != 1; then
+       error "Incorrect link count on extracted file"
+fi
+if test "`stat -c %i tmp/subdir/hello`" = "`stat -c %i tmp/subdir/hello2`"; then
+       error "Incorrect inode number"
+fi
+if ! test -L tmp/subdir/hello || ! test -L tmp/subdir/hello2; then
+       error "Expected symlinks, but found non-symlinks"
+fi
 rm -rf dir.wim tmp
 
 # imagex mount
@@ -205,65 +386,130 @@ rm -rf dir.wim tmp
 for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
        echo "Using flag $flag"
        echo "Testing mounting WIM read-only"
-       imagex capture dir dir.wim $flag
+       if ! imagex capture dir dir.wim $flag; then
+               error "Failed to capture WIM"
+       fi
        mkdir tmp
-       imagex mount dir.wim dir tmp
+       if ! imagex mount dir.wim dir tmp; then
+               error "Failde to mount test WIM read-only"
+       fi
        echo "Testing extracting file from mounted read-only WIM"
-       cp tmp/lz.c lz.c
-       diff -q dir/lz.c lz.c
-       diff -q tmp/lz.c dir/lz.c
+       if ! cp tmp/lz.c lz.c; then
+               error "Failed to extract file from read-only mounted WIM"
+       fi
+       if ! diff -q dir/lz.c lz.c; then
+               error "Extracted file does not match copy in mounted WIM"
+       fi
+       if ! diff -q tmp/lz.c dir/lz.c; then
+               error "Extractef file does not match original"
+       fi
        rm -f lz.c
        echo "Testing modifying mounted read-only WIM (should fail)"
-       ! rm tmp/lz.c
-       ! touch tmp/newfile
-       ! echo 3 > tmp/newfile
+       if rm tmp/lz.c; then
+               error "Removing file from read-only mounted WIM didn't fail"
+       fi
+       if touch tmp/newfile; then
+               error "Creating file on read-only mounted WIM didn't fail"
+       fi
+       if echo 3 > tmp/lz.c; then
+               error "Writing to file on read-only mounted WIM didn't fail"
+       fi
        echo "Testing diff of mounted read-only WIM with original directory"
-       diff -q -r tmp dir
+       if ! diff -q -r tmp dir; then
+               error "Recursive diff of read-only mounted WIM with original directory failed"
+       fi
        echo "Testing unmount of read-only filesystem"
-       imagex unmount tmp
+       if ! imagex unmount tmp; then
+               error "Unmounting read-only WIM failed"
+       fi
        echo "Testing unmount of read-only filesystem with --commit given"
-       imagex mount dir.wim dir tmp
-       imagex unmount tmp --commit
+       if ! imagex mount dir.wim dir tmp; then
+               error "Failed to re-mount WIM read-only"
+       fi
+       if ! imagex unmount tmp --commit; then
+               error "Failed to unmount read-only WIM with --commit flag (should be ignored)"
+       fi
        rm -rf tmp dir.wim
 done
 
 # imagex mountrw
-for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
-       echo "Using flag $flag"
-       echo "Testing mounting WIM read-write"
-       imagex capture dir dir.wim $flag
-       mkdir tmp
-       imagex mountrw dir.wim dir tmp
-       echo "Testing unmounting WIM unmodified"
-       imagex unmount tmp
-       echo "Testing unmounting WIM unmodified with --commit and --check"
-       imagex mountrw dir.wim dir tmp
-       imagex unmount tmp --commit --check
-       echo "Testing removing file from mounted WIM"
-       imagex mountrw dir.wim dir tmp
-       rm tmp/lz.c
-       test ! -e tmp/lz.c
-       echo "Testing making directory in mounted WIM"
-       mkdir tmp/newdir
-       test -d tmp/newdir
-       echo "Testing making new empty file in mounted WIM"
-       touch tmp/newdir/empty_file
-       test -e tmp/newdir/empty_file
-       test `stat -c %s tmp/newdir/empty_file` = 0;
-       echo "Testing making new non-empty file in mounted WIM"
-       dd if=/dev/zero of=tmp/newdir/zeroes1 bs=1 count=4096
-       dd if=/dev/zero of=tmp/newdir/zeroes2 bs=4096 count=1
-       cmp tmp/newdir/zeroes1 tmp/newdir/zeroes2
-       echo "Unmounting WIM with changes committed and --check"
-       imagex unmount tmp --commit --check
-       test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" = "yes";
-       rm -rf tmp
-       imagex apply dir.wim tmp
-       cmp tmp/newdir/zeroes1 tmp/newdir/zeroes2
-       test `stat -c %s tmp/newdir/empty_file` = 0;
-       test `stat -c %s tmp/newdir/zeroes1` = 4096;
-       rm -rf tmp dir.wim
-done
+echo "Testing mounting WIM read-write"
+if ! imagex capture dir dir.wim; then
+       error "Failed to capture WIM"
+fi
+mkdir tmp
+if ! imagex mountrw dir.wim dir tmp; then
+       error "Failed to mount test WIM read-write"
+fi
+echo "Testing unmounting WIM unmodified"
+if ! imagex unmount tmp; then
+       error "Failed to unmount test WIM unmodified"
+fi
+echo "Testing unmounting WIM unmodified with --commit and --check"
+if ! imagex mountrw dir.wim dir tmp; then
+       error "Failed to re-mount test WIM read-write"
+fi
+if ! imagex unmount tmp --commit --check; then
+       error "Failed to unmount read-write mounted WIM with changes commited (no changes made)"
+fi
+echo "Testing removing file from mounted WIM"
+if ! imagex mountrw dir.wim dir tmp; then
+       error "Failed to re-mount test WIM read-write"
+fi
+if ! rm tmp/lz.c; then
+       error "Failed to remove file from read-write mounted WIM"
+fi
+if test -f tmp/lz.c; then
+       error "Removing file from read-write mounted WIM failed"
+fi
+echo "Testing making directory in mounted WIM"
+if ! mkdir tmp/newdir; then
+       error "Failed to make directory in read-write mounted WIM"
+fi
+if ! test -d tmp/newdir; then
+       error "Making directory in read-write mounted WIM failed"
+fi
+echo "Testing making new empty file in mounted WIM"
+if ! touch tmp/newdir/empty_file; then
+       error "Could not create new empty file in read-write mounted WIM"
+fi
+if ! test -f tmp/newdir/empty_file; then
+       error "New empty file not created correctly in read-write mounted WIM"
+fi
+if ! test "`stat -c %s tmp/newdir/empty_file`" = 0; then
+       error "New empty file in read-write mounted WIM is not empty"
+fi
+echo "Testing making new non-empty file in mounted WIM"
+if ! dd if=/dev/zero of=tmp/newdir/zeroes1 bs=1 count=4096; then
+       error "Failed to make new non-empty file in mounted WIM"
+fi
+if ! dd if=/dev/zero of=tmp/newdir/zeroes2 bs=4096 count=1; then
+       error "Failed to make new non-empty file in mounted WIM"
+fi
+if ! diff -q tmp/newdir/zeroes1 tmp/newdir/zeroes2; then
+       error "New files in mounted WIM not made correctly"
+fi
+echo "Unmounting WIM with changes committed and --check"
+if ! imagex unmount tmp --commit --check; then
+       error "Failed to unmount read-write mounted WIM"
+fi
+if test "`imagex info dir.wim | grep Integrity | awk '{print $3}'`" != "yes"; then
+       error "Integrity information was not included"
+fi
+rm -rf tmp
+if ! imagex apply dir.wim tmp; then
+       error "Failed to apply WIM we had previously mounted read-write"
+fi
+if ! diff -q tmp/newdir/zeroes1 tmp/newdir/zeroes2; then
+       error "The new non-empty files we made in the read-write mounted WIM were not extracted correctly"
+fi
+if test `stat -c %s tmp/newdir/empty_file` != 0; then
+       error "The new empty file we made in the read-write mounted WIM was not extracted correctly"
+fi
+if test `stat -c %s tmp/newdir/zeroes1` != 4096; then
+       error "The new non-empty files we made in the read-write mounted WIM were not extracted correctly"
+fi
+rm -rf tmp dir.wim
 
 # imagex split, imagex join
 
@@ -274,20 +520,44 @@ for i in `seq 1 100`; do
 done
 for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
        echo "Using flag $flag"
-       imagex capture tmp tmp.wim $flag
+       if ! imagex capture tmp tmp.wim $flag; then
+               error "Failed to capture test WIM"
+       fi
        echo "Splitting WIM into 1 MiB chunks"
-       imagex split tmp.wim tmp.swm 1
+       if ! imagex split tmp.wim tmp.swm 1; then
+               error "Failed to split WIM"
+       fi
        echo "Verifying the split WIMs (some errors expected)"
-       test "`imagex info tmp.swm | grep 'Part Number' | awk '{print $3}'`" = "1/4"
-       imagex dir tmp.swm > /dev/null
-       test -e tmp2.swm && ! imagex dir tmp2.swm
-       ! imagex info tmp.swm --boot 0 # Unsupported, should fail
+       if test "`imagex info tmp.swm | grep 'Part Number' | awk '{print $3}'`" != "1/4"; then
+               error "Part number of split WIM not correct"
+       fi
+       if ! imagex dir tmp.swm > /dev/null; then
+               error "Failed to list files in split WIM"
+       fi
+       if ! test -e tmp2.swm; then
+               error "Could not find split-WIM part 2"
+       fi
+       if imagex dir tmp2.swm > /dev/null; then
+               error "Listed files in part 2 of split WIM (this should have failed)"
+       fi
+
+       # Unsupported, should fail
+       if imagex info tmp.swm --boot 0; then
+               error "Should not have been able to change boot index of split WIM"
+       fi
        echo "Joining the split WIMs and applying the result"
-       imagex join tmp2.wim tmp*.wim
-       imagex apply tmp2.wim tmp2
-       imagex apply tmp.wim tmp3
-       diff -q -r tmp tmp2
-       diff -q -r tmp tmp3
+       if ! imagex join tmp2.wim tmp*.wim; then
+               error "Failed to join split WIMs"
+       fi
+       if ! imagex apply tmp2.wim tmp2; then
+               error "Failed to apply joined split WIM"
+       fi
+       if ! imagex apply tmp.wim tmp3; then
+               error "Failed to apply test WIM"
+       fi
+       if ! diff -q -r tmp tmp2 || ! diff -q -r tmp tmp3; then
+               error "Recursive diff of applied joined split WIM with original directory failed"
+       fi
        rm -f *.wim *.swm
        rm -rf tmp2 tmp3
 done