]> wimlib.net Git - wimlib/commitdiff
Test suite and mount updates
authorEric Biggers <ebiggers3@gmail.com>
Sun, 2 Sep 2012 05:14:58 +0000 (00:14 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 2 Sep 2012 05:14:58 +0000 (00:14 -0500)
Makefile.am
src/mount.c
tests/common_tests.sh [new file with mode: 0644]
tests/test-imagex
tests/test-imagex-capture_and_apply [new file with mode: 0755]
tests/test-imagex-mount [new file with mode: 0755]
tests/test-imagex-ntfs
tests/tree-cmp.c [moved from tests/ntfs-cmp.c with 80% similarity]

index f05e58ddd4898eff7d5d1f80ef5f8af6593d270e..2e18838653097e6db609af10248f22a2c3e244d2 100644 (file)
@@ -91,6 +91,7 @@ EXTRA_DIST =                  \
        build-aux/strip_fPIC.sh \
        debian                  \
        programs/install.cmd
        build-aux/strip_fPIC.sh \
        debian                  \
        programs/install.cmd
+       tests/common_tests.sh
 
 pkgconfigdir   = @pkgconfigdir@
 pkgconfig_DATA = wimlib.pc
 
 pkgconfigdir   = @pkgconfigdir@
 pkgconfig_DATA = wimlib.pc
@@ -115,8 +116,13 @@ man1_MANS =                        \
 
 $(man1_MANS): config.status
 
 
 $(man1_MANS): config.status
 
-check_PROGRAMS = tests/ntfs-cmp
-tests_ntfs_cmp_SOURCES = tests/ntfs-cmp.c
-dist_check_SCRIPTS = tests/test-imagex tests/test-imagex-ntfs
+check_PROGRAMS = tests/tree-cmp
+tests_tree_cmp_SOURCES = tests/tree-cmp.c
+
+dist_check_SCRIPTS = tests/test-imagex                         \
+                    tests/test-imagex-mount                    \
+                    tests/test-imagex-capture_and_apply        \
+                    tests/test-imagex-ntfs
+
 TESTS = $(dist_check_SCRIPTS)
 
 TESTS = $(dist_check_SCRIPTS)
 
index 6f50a4e5931d5d2b59a8dace45422edb7fb92b23..5b1e09e35bed4a62f9be61d26846ace89982ec52 100644 (file)
@@ -1376,6 +1376,31 @@ static int wimfs_readlink(const char *path, char *buf, size_t buf_len)
        return ret;
 }
 
        return ret;
 }
 
+/* Creation time, write time, access time */
+static void
+dentry_link_group_set_times(struct dentry *dentry, u64 times[3])
+{
+       struct dentry *cur = dentry;
+       do {
+               if (times[0])
+                       dentry->creation_time = times[0];
+               if (times[1])
+                       dentry->last_write_time = times[1];
+               if (times[2])
+                       dentry->last_access_time = times[2];
+       } while ((cur = container_of(dentry->link_group_list.next,
+                                    struct dentry,
+                                    link_group_list)) != dentry);
+}
+
+static void
+dentry_link_group_update_times(struct dentry *dentry)
+{
+       u64 now = get_wim_timestamp();
+       u64 times[3] = {now, now, now};
+       dentry_link_group_set_times(dentry, times);
+}
+
 /* Close a file. */
 static int wimfs_release(const char *path, struct fuse_file_info *fi)
 {
 /* Close a file. */
 static int wimfs_release(const char *path, struct fuse_file_info *fi)
 {
@@ -1388,12 +1413,6 @@ static int wimfs_release(const char *path, struct fuse_file_info *fi)
                return 0;
        }
 
                return 0;
        }
 
-       if (flags_writable(fi->flags) && fd->dentry) {
-               u64 now = get_wim_timestamp();
-               fd->dentry->last_access_time = now;
-               fd->dentry->last_write_time = now;
-       }
-
        return close_wimlib_fd(fd);
 }
 
        return close_wimlib_fd(fd);
 }
 
@@ -1655,7 +1674,7 @@ static int wimfs_truncate(const char *path, off_t size)
                ret = extract_resource_to_staging_dir(dentry, stream_idx,
                                                      &lte, size);
        }
                ret = extract_resource_to_staging_dir(dentry, stream_idx,
                                                      &lte, size);
        }
-       dentry_update_all_timestamps(dentry);
+       dentry_link_group_update_times(dentry);
        return ret;
 }
 
        return ret;
 }
 
@@ -1698,18 +1717,20 @@ static int wimfs_utimens(const char *path, const struct timespec tv[2])
        struct dentry *dentry = get_dentry(w, path);
        if (!dentry)
                return -ENOENT;
        struct dentry *dentry = get_dentry(w, path);
        if (!dentry)
                return -ENOENT;
+       u64 times[3] = {0, 0, 0};
        if (tv[0].tv_nsec != UTIME_OMIT) {
                if (tv[0].tv_nsec == UTIME_NOW)
        if (tv[0].tv_nsec != UTIME_OMIT) {
                if (tv[0].tv_nsec == UTIME_NOW)
-                       dentry->last_access_time = get_wim_timestamp();
+                       times[2] = get_wim_timestamp();
                else
                else
-                       dentry->last_access_time = timespec_to_wim_timestamp(&tv[0]);
+                       times[2] = timespec_to_wim_timestamp(&tv[0]);
        }
        if (tv[1].tv_nsec != UTIME_OMIT) {
                if (tv[1].tv_nsec == UTIME_NOW)
        }
        if (tv[1].tv_nsec != UTIME_OMIT) {
                if (tv[1].tv_nsec == UTIME_NOW)
-                       dentry->last_write_time = get_wim_timestamp();
+                       times[1] = get_wim_timestamp();
                else
                else
-                       dentry->last_write_time = timespec_to_wim_timestamp(&tv[1]);
+                       times[1] = timespec_to_wim_timestamp(&tv[1]);
        }
        }
+       dentry_link_group_set_times(dentry, times);
        return 0;
 }
 
        return 0;
 }
 
@@ -1736,6 +1757,12 @@ static int wimfs_write(const char *path, const char *buf, size_t size,
        if (ret == -1)
                return -errno;
 
        if (ret == -1)
                return -errno;
 
+       if (fd->dentry) {
+               u64 now = get_wim_timestamp();
+               u64 times[3] = {0, now, now};
+               dentry_link_group_set_times(fd->dentry, times);
+       }
+
        return ret;
 }
 
        return ret;
 }
 
@@ -1936,6 +1963,7 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
                /* Read-only mount */
                strcat(optstring, ",ro");
        }
                /* Read-only mount */
                strcat(optstring, ",ro");
        }
+       strcat(optstring, ",subtype=wimfs,attr_timeout=0");
        argv[argc] = NULL;
 
 #ifdef ENABLE_DEBUG
        argv[argc] = NULL;
 
 #ifdef ENABLE_DEBUG
diff --git a/tests/common_tests.sh b/tests/common_tests.sh
new file mode 100644 (file)
index 0000000..6e585a8
--- /dev/null
@@ -0,0 +1,71 @@
+
+msg "nothing"
+do_test ""
+
+msg "a single file"
+do_test "echo 1 > file"
+
+msg "a single directory"
+do_test "mkdir dir"
+
+msg "subdirectory with file"
+do_test "mkdir dir; echo 1 > dir/file"
+
+msg "empty file"
+do_test "echo -n > empty_file"
+
+msg "two empty files"
+do_test "echo -n > empty_file_1; echo -n > empty_file_2"
+
+msg "hard link in same directory"
+do_test "echo 1 > file; ln file link"
+
+msg "hard link between empty files"
+do_test "echo -n > empty_file; ln empty_file link"
+
+msg "relative symbolic link"
+do_test "echo 1 > file; ln -s file symlink"
+
+msg "absolute symbolic link"
+do_test "echo 1 > file; ln -s /some/absolute/target symlink"
+
+msg "large file"
+do_test "dd if=/dev/zero of=file bs=4096 count=10 &> /dev/null"
+
+msg "many nested directories"
+do_test 'mkdir dir; mkdir dir/subdir; mkdir dir/subdir/subdir2; mkdir dir/subdir/subdir3'
+
+msg "identical files and symlinks in subdirectory"
+do_test 'mkdir dir;
+        echo 888 > dir/file;
+        echo 888 > dir/idfile2;
+        ln -s ../dir dir/circle; ln -s file dir/filelink'
+
+msg "hard link group and identical files not hard linked"
+do_test 'echo 888 > file;
+        echo 888 > file2;
+        ln file link;
+        ln file link2;
+        echo 888 > file3'
+
+msg "C source code of wimlib"
+do_test 'cp $srcdir/src/*.{c,h} .'
+
+msg "tons of random stuff"
+do_test 'echo -n 8 > file;
+        ln file hardlink;
+        ln -s hardlink symlink;
+        echo -n 8 > identical file;
+        dd if=/dev/urandom of=randomfile bs=4096 count=10 &>/dev/null;
+        mkdir dir;
+        mkdir anotherdir;
+        cp file anotherdir;
+        ln file anotherdir/anotherhardlink;
+        ln -s .. anotherdir/anothersymlink;
+        ln -s anothersymlink anotherdir/symlinktosymlink;
+        echo -n 33 > anotherfile;
+        echo -n > emptyfile;
+        mkdir dir/subdir;
+        ln file dir/subdir/file;
+        echo -n 8 > dir/subdir/file2;
+        ln dir/subdir/file dir/subdir/link;'
index 36e02534fcdade96b336bd79be1d6170795d79a1..dc67da2af0a8237e458d82aa52746ed5be3ff6a2 100755 (executable)
@@ -10,13 +10,15 @@ cd tests
 
 imagex() {
        echo "imagex $@"
 
 imagex() {
        echo "imagex $@"
-       ../imagex $@ 
+       ../imagex "$@" > /dev/null
+}
+
+imagex_info() {
+       echo "imagex info $@"
+       ../imagex info "$@"
 }
 
 cleanup() {
 }
 
 cleanup() {
-       if [ -d tmp ] && mountpoint tmp > /dev/null; then
-               fusermount -u tmp > /dev/null;
-       fi
        rm -rf dir* tmp* *.wim *.swm
 }
 trap cleanup exit
        rm -rf dir* tmp* *.wim *.swm
 }
 trap cleanup exit
@@ -55,8 +57,8 @@ for comp_type in None LZX XPRESS; do
        if ! imagex apply dir.wim tmp; then
                error "'imagex apply' 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"
+       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 ! diff -q -r dir tmp; then
                error "Recursive diff of extracted directory with original failed"
@@ -84,38 +86,38 @@ done
 
 echo "Testing capture of WIM with default name and description"
 imagex capture dir dir.wim
 
 echo "Testing capture of WIM with default name and description"
 imagex capture dir dir.wim
-if ! test "`imagex info dir.wim | grep Name | awk '{print $2}'`" = "dir"; then
+if ! test "`imagex_info dir.wim | grep Name | awk '{print $2}'`" = "dir"; then
        error "WIM name not set correctly"
 fi
        error "WIM name not set correctly"
 fi
-if ! test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = ""; then
+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
        error "WIM description not set correctly"
 fi
 
 echo "Testing capture of WIM with default boot flag"
 imagex capture dir dir.wim
-if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
+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"
        error "WIM boot flag not set correctly"
 fi
 
 echo "Testing changing image bootable flag"
-if ! imagex info dir.wim 1 --boot; then
+if ! imagex_info dir.wim 1 --boot; then
        error "Failed to change bootable image"
 fi
        error "Failed to change bootable image"
 fi
-if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
+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"
        error "Bootable image not changed correctly"
 fi
 echo "Testing changing image bootable flag"
-if ! imagex info dir.wim 0 --boot; then
+if ! imagex_info dir.wim 0 --boot; then
        error "Failed to reset bootable image"
 fi
        error "Failed to reset bootable image"
 fi
-if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
+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)"
        error "Bootable image not reset correctly"
 fi
 echo "Testing changing image bootable flag to invalid image (this should generate errors)"
-if imagex info dir.wim 2 --boot; then
+if imagex_info dir.wim 2 --boot; then
        error "Succeeded in changing bootable image to invalid number"
 fi
        error "Succeeded in changing bootable image to invalid number"
 fi
-if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "0"; then
+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
        error "Boot flag was changed even though the change command was supposed to fail"
 fi
 rm -rf dir.wim tmp
@@ -124,30 +126,30 @@ echo "Testing capture of WIM with name and description"
 if ! imagex capture dir dir.wim "myname" "mydesc"; then
        error "Failed to capture WIM with specified name and description"
 fi
 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
+if ! test "`imagex_info dir.wim | grep Name | awk '{print $2}'`" = "myname"; then
        error "WIM name not set correctly"
 fi
        error "WIM name not set correctly"
 fi
-if ! test "`imagex info dir.wim | grep Description | awk '{print $2}'`" = "mydesc"; then
+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"
        error "WIM name not set correctly"
 fi
 echo "Testing printing WIM lookup table"
-if ! imagex info --lookup-table dir.wim > /dev/null; then
+if ! imagex_info --lookup-table dir.wim > /dev/null; then
        error "Failed to print WIM lookup table"
 fi
 echo "Testing printing WIM header"
        error "Failed to print WIM lookup table"
 fi
 echo "Testing printing WIM header"
-if ! imagex info --header dir.wim > /dev/null; then
+if ! imagex_info --header dir.wim > /dev/null; then
        error "Failed to print WIM header"
 fi
 echo "Testing printing WIM XML info"
        error "Failed to print WIM header"
 fi
 echo "Testing printing WIM XML info"
-if ! imagex info --xml dir.wim > /dev/null; then
+if ! imagex_info --xml dir.wim > /dev/null; then
        error "Failed to print WIM XML data"
 fi
 echo "Testing extracting WIM XML info"
        error "Failed to print WIM XML data"
 fi
 echo "Testing extracting WIM XML info"
-if ! imagex info --extract-xml=dir.xml dir.wim; then
+if ! imagex_info --extract-xml=dir.xml dir.wim; then
        error "Failed to extract WIM XML data"
 fi
 echo "Testing printing WIM metadata"
        error "Failed to extract WIM XML data"
 fi
 echo "Testing printing WIM metadata"
-if ! imagex info --metadata dir.wim > /dev/null; then
+if ! imagex_info --metadata dir.wim > /dev/null; then
        error "Failed to print WIM metadata"
 fi
 rm -rf dir.wim tmp dir.xml
        error "Failed to print WIM metadata"
 fi
 rm -rf dir.wim tmp dir.xml
@@ -156,7 +158,7 @@ echo "Testing capture of bootable WIM"
 if ! imagex capture dir dir.wim --boot; then
        error "Failed to capture bootable WIM"
 fi
 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
+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
        error "Boot flag on bootable WIM not set correctly"
 fi
 rm -rf dir.wim tmp
@@ -167,7 +169,7 @@ echo "Testing capture of WIM with integrity table"
 if ! imagex capture dir dir.wim --check; then
        error "Failed to capture WIM with integrity table"
 fi
 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
+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"
 fi
 if ! imagex apply --check dir.wim tmp; then
@@ -185,7 +187,7 @@ imagex capture dir dir.wim
 if ! imagex append dir2 dir.wim; then
        error "Appending WIM image failed"
 fi
 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
+if ! test "`imagex_info dir.wim | grep 'Image Count' | awk '{print $3}'`" = 2; then
        error "WIM image count not correct"
 fi
 
        error "WIM image count not correct"
 fi
 
@@ -201,56 +203,56 @@ echo "Testing appending WIM image with integrity check"
 if ! imagex append dir2 dir.wim "newname2" --check; then
        error "Appending WIM image failed"
 fi
 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
+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"
 if ! imagex append dir2 dir.wim "newname3"; then
        error "Appending WIM image failed"
 fi
        error "Integrity table not set correctly on image append"
 fi
 echo "Testing appending WIM image with no integrity check"
 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
+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
        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
+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"
 if ! imagex delete dir.wim 1; then
        error "Failed to delete WIM image"
 fi
        error "WIM does not contain the expected 5 images"
 fi
 echo "Testing deleting first WIM image"
 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
+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"
 if ! imagex delete dir.wim 4; then
        error "Failed to delete WIM image"
 fi
        error "WIM image not deleted correctly"
 fi
 echo "Testing deleting last WIM image"
 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
+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)"
 if imagex delete dir.wim 4; then
        error "Expected to fail to delete non-existent WIM image"
 fi
        error "WIM image not deleted correctly"
 fi
 echo "Testing deleting invalid WIM image (this should generate errors)"
 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
+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"
 if ! imagex delete dir.wim all; then
        error "Failed to delete all images from WIM"
 fi
        error "Image count changed even though we intentionally failed to delete an image"
 fi
 echo "Testing deleting all WIM images"
 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
+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"
 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
        error "Couldn't delete all WIM images correctly"
 fi
 echo "Testing appending directory to empty WIM and making it bootable"
 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
+if ! test "`imagex_info dir.wim | grep Integrity | awk '{print $3}'`" = "yes"; then
        error "Integrity check not found"
 fi
        error "Integrity check not found"
 fi
-if ! test "`imagex info dir.wim | grep Boot | awk '{print $3}'`" = "1"; then
+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)"
        error "Bootable image not set correctly"
 fi
 echo "Testing appending non-directory (should generate errors)"
@@ -369,135 +371,6 @@ if ! test -L tmp/subdir/hello -o -L tmp/subdir/hello2 -o -L tmp/subdir/hellolink
 fi
 rm -rf dir.wim tmp
 
 fi
 rm -rf dir.wim tmp
 
-# imagex mount
-
-for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
-       echo "Using flag $flag"
-       echo "Testing mounting WIM read-only"
-       if ! imagex capture dir dir.wim $flag; then
-               error "Failed to capture WIM"
-       fi
-       mkdir 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"
-       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)"
-       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"
-       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"
-       if ! imagex unmount tmp; then
-               error "Unmounting read-only WIM failed"
-       fi
-       echo "Testing unmount of read-only filesystem with --commit given"
-       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
-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
 
 
 # imagex split, imagex join
 
@@ -516,7 +389,7 @@ for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
                error "Failed to split WIM"
        fi
        echo "Verifying the split WIMs (some errors expected)"
                error "Failed to split WIM"
        fi
        echo "Verifying the split WIMs (some errors expected)"
-       if test "`imagex info tmp.swm | grep 'Part Number' | awk '{print $3}'`" != "1/4"; then
+       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 "Part number of split WIM not correct"
        fi
        if ! imagex dir tmp.swm > /dev/null; then
@@ -530,7 +403,7 @@ for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
        fi
 
        # Unsupported, should fail
        fi
 
        # Unsupported, should fail
-       if imagex info tmp.swm --boot 0; then
+       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"
                error "Should not have been able to change boot index of split WIM"
        fi
        echo "Joining the split WIMs and applying the result"
@@ -562,14 +435,14 @@ fi
 if ! imagex export dir.wim dir new.wim; then
        error "Failed to export single image to new WIM"
 fi
 if ! imagex export dir.wim dir new.wim; then
        error "Failed to export single image to new WIM"
 fi
-if test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" != 1; then
+if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 1; then
        error "Exporting single image to new WIM wasn't done correctly"
 fi
 echo "Testing export of single image to existing WIM"
 if ! imagex export dir.wim dir2 new.wim; then
        error "Failed to export single image to existing WIM"
 fi
        error "Exporting single image to new WIM wasn't done correctly"
 fi
 echo "Testing export of single image to existing WIM"
 if ! imagex export dir.wim dir2 new.wim; then
        error "Failed to export single image to existing WIM"
 fi
-if test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then
+if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then
        error "Exporting single image to existing WIM wasn't done correctly"
 fi
 echo "Testing export of single image to existing WIM using wrong compression type"
        error "Exporting single image to existing WIM wasn't done correctly"
 fi
 echo "Testing export of single image to existing WIM using wrong compression type"
@@ -581,7 +454,7 @@ echo "Testing export of multiple images to new WIM"
 if ! imagex export dir.wim all new.wim; then
        error "Failed to export multiple images to new WIM"
 fi
 if ! imagex export dir.wim all new.wim; then
        error "Failed to export multiple images to new WIM"
 fi
-if test "`imagex info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then
+if test "`imagex_info new.wim | grep 'Image Count' | awk '{print $3}'`" != 2; then
        error "Exporting multiple images to new WIM wasn't done correctly"
 fi
 if ! imagex capture dir2 new.wim newname; then
        error "Exporting multiple images to new WIM wasn't done correctly"
 fi
 if ! imagex capture dir2 new.wim newname; then
@@ -595,7 +468,7 @@ echo "Testing export of multiple images to existing WIM with --boot"
 if ! imagex capture dir2 new.wim newname; then
        error "Failed to capture test WIM"
 fi
 if ! imagex capture dir2 new.wim newname; then
        error "Failed to capture test WIM"
 fi
-if ! imagex info dir.wim --boot 1; then
+if ! imagex_info dir.wim --boot 1; then
        error "Failed to set boot index on test WIM"
 fi
 if ! imagex export dir.wim all new.wim --boot; then
        error "Failed to set boot index on test WIM"
 fi
 if ! imagex export dir.wim all new.wim --boot; then
@@ -605,7 +478,7 @@ echo "Testing export of multiple images to existing WIM with --boot, but no boot
 if ! imagex capture dir2 new.wim newname; then
        error "Failed to capture test WIM"
 fi
 if ! imagex capture dir2 new.wim newname; then
        error "Failed to capture test WIM"
 fi
-if ! imagex info dir.wim --boot 0; then
+if ! imagex_info dir.wim --boot 0; then
        error "Failed to clear boot index on test WIM"
 fi
 if imagex export dir.wim all new.wim --boot; then
        error "Failed to clear boot index on test WIM"
 fi
 if imagex export dir.wim all new.wim --boot; then
diff --git a/tests/test-imagex-capture_and_apply b/tests/test-imagex-capture_and_apply
new file mode 100755 (executable)
index 0000000..0a53aee
--- /dev/null
@@ -0,0 +1,143 @@
+#!/bin/bash
+
+# Test capturing and applying a WIM image in the normal (non-NTFS) capture mode
+#
+# Add in some tests with WIM splitting, joining, and exporting as well.
+#
+# Test all three compression modes (None, XPRESS, and LZX).
+#
+# Also, test if the capture configuration file works correctly.
+
+set -e
+srcdir=${srcdir:-.}
+srcdir=`realpath $srcdir`
+cd tests
+
+imagex() {
+       echo "imagex $@"
+       ../imagex "$@" > /dev/null
+}
+
+imagex_info() {
+       echo "imagex info $@"
+       ../imagex info "$@"
+}
+
+init() {
+       mkdir in.dir out.dir
+}
+
+cleanup() {
+       rm -rf in.dir out.dir test*.wim test*.swm
+}
+
+error() {
+       echo "****************************************************************"
+       echo "                         Test failure                           "
+       echo $*
+       echo "****************************************************************"
+       exit 1
+}
+
+wim_ctype() {
+       ../imagex info $1 | grep Compression | awk '{print $2}'
+}
+
+do_tree_cmp() {
+       if ! ./tree-cmp in.dir out.dir; then
+               if [ -x /usr/bin/tree ]; then
+                       echo "Dumping tree of applied image"
+                       echo "(Note: compression type was $ctype)"
+                       tree out.dir --inodes -F -s --noreport
+                       error 'Information was lost or corrupted while capturing
+                               and then applying a directory tree'
+               fi
+       fi
+}
+
+image_name=0
+do_test() {
+       for ctype in None LZX XPRESS; do
+
+               # Can we capture the WIM, apply it, and get the same result?
+               cd in.dir
+               eval "$1"
+               cd ..
+               if [ -x /usr/bin/tree -a "$ctype" = "None" ]; then
+                       tree in.dir --inodes -F -s --noreport
+               fi
+               if ! imagex capture in.dir test.wim --compress=$ctype; then
+                       error "Failed to capture directory tree into a WIM"
+               fi
+               if ! imagex apply test.wim 1 out.dir; then
+                       error "Failed to apply WIM to directory"
+               fi
+               if [ `wim_ctype test.wim` != $ctype ]; then
+                       error "'imagex info' didn't report the compression type on the captured WIM correctly"
+               fi
+               do_tree_cmp
+               rm -rf out.dir/*
+
+               # Can we split the WIM, apply the split WIM, join the split WIM,
+               # and apply the joined WIM, and get the same results every time?
+               if ! imagex split test.wim test.swm 0.01M; then
+                       error "Failed to split WIM"
+               fi
+               if ! imagex apply test.swm 1 out.dir --ref "test*.swm" ; then
+                       error "Failed to apply split WIM"
+               fi
+               do_tree_cmp
+               rm -rf out.dir/* test.wim
+               if ! imagex join test.wim test*.swm; then
+                       error "Failed to join split WIM"
+               fi
+               if ! imagex apply test.wim out.dir; then
+                       error "Failed to apply joined WIM"
+               fi
+               do_tree_cmp
+               rm -rf out.dir/*
+
+               # Can we export the image to another WIM, apply it, and get the
+               # same results?
+               (( image_name++ )) || true
+               if ! imagex export test.wim 1 test2.wim "$image_name"; then
+                       error "Failed to export WIM image"
+               fi
+
+               if ! imagex apply test2.wim "$image_name" out.dir; then
+                       error "Failed to apply exported WIM image"
+               fi
+               do_tree_cmp
+
+               rm -rf out.dir/* in.dir/* test.wim test*.swm
+
+       done
+}
+
+msg() {
+       echo "--------------------------------------------------------------------"
+       echo "Testing image capture and application of directory containing $1"
+       echo "--------------------------------------------------------------------"
+}
+
+cleanup
+init
+
+. common_tests.sh
+
+# Make sure exclusion list works
+msg "Testing default capture configuration file"
+touch in.dir/hiberfil.sys
+mkdir -p "in.dir/System Volume Information/subdir"
+imagex capture in.dir test.wim
+imagex apply test.wim out.dir
+if [ -e out.dir/hiberfil.sys -o -e "out.dir/System Volume Information" ]; then
+       error "Files were not excluded from capture as expected"
+fi
+rm -rf out.dir/* in.dir/*
+
+cleanup
+
+echo "**********************************************************"
+echo "          imagex capture/apply tests passed               "
+echo "**********************************************************"
diff --git a/tests/test-imagex-mount b/tests/test-imagex-mount
new file mode 100755 (executable)
index 0000000..cd3317a
--- /dev/null
@@ -0,0 +1,275 @@
+#!/bin/sh
+
+# Test WIM mounting
+
+set -e
+srcdir=${srcdir:-.}
+srcdir=`realpath $srcdir`
+cd tests
+
+imagex() {
+       echo "imagex $@"
+       ../imagex $@  > /dev/null
+}
+
+imagex_info() {
+       echo "imagex info $@"
+       ../imagex info "$@"
+}
+
+imagex_mountrw() {
+       echo "imagex mountrw $@"
+       ../imagex mountrw --debug "$@" &> mount.log &
+       while ! mountpoint $2 >& /dev/null; do
+               sleep 0.01;
+       done
+       return 0
+}
+
+cleanup() {
+       if mountpoint tmp &> /dev/null; then
+               fusermount -u tmp > /dev/null;
+       fi
+       if mountpoint tmp.mnt &> /dev/null; then
+               fusermount -u tmp.mnt > /dev/null;
+       fi
+       rm -rf dir* tmp* *.wim *.swm empty.wim tmp.orig tmp.mnt \
+                       tmp.apply mount.log
+}
+init() {
+       mkdir dir
+       cp $srcdir/src/*.c $srcdir/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
+
+       mkdir dir2
+       echo 'testing' > dir2/file
+       dd if=/dev/zero of=dir2/zeroes bs=4096 count=5
+       mkdir tmp.empty tmp.mnt tmp.apply tmp.orig
+       imagex capture tmp.empty empty.wim
+}
+
+error() {
+       echo "**********************************************"
+       echo "                  Test failure                "
+       echo $*
+       echo "**********************************************"
+       exit 1
+}
+
+cleanup
+init
+
+# imagex mount
+
+for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do
+       echo "Using flag $flag"
+       echo "Testing mounting WIM read-only"
+       if ! imagex capture dir dir.wim $flag; then
+               error "Failed to capture WIM"
+       fi
+       mkdir 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"
+       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)"
+       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"
+       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"
+       if ! imagex unmount tmp; then
+               error "Unmounting read-only WIM failed"
+       fi
+       echo "Testing unmount of read-only filesystem with --commit given"
+       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
+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
+
+# Now do some tests using tar.
+do_tree_cmp() {
+       if ! ./tree-cmp $1 $2; then
+               if [ -x /usr/bin/tree ]; then
+                       echo "Dumping tree of applied image"
+                       tree $2 --inodes -F -s --noreport
+                       error 'Information was lost or corrupted while capturing
+                               and then applying a directory tree'
+               fi
+       fi
+}
+
+msg() {
+       echo "--------------------------------------------------------------------"
+       echo "Testing making $1 on read-write mounted WIM"
+       echo "--------------------------------------------------------------------"
+}
+
+do_test() {
+
+       # Create tree, tar it up, and untar it on an empty WIM image mounted
+       # read-write
+
+       cp empty.wim test.wim
+
+       cd tmp.orig
+       eval "$1"
+       if [ -x /usr/bin/tree ]; then
+               tree . --inodes -F -s --noreport
+       fi
+       tar cf ../test.tar .
+       cd ..
+
+       if ! imagex_mountrw test.wim tmp.mnt; then
+               error "Failed to mount WIM read-write"
+       fi
+
+       cd tmp.mnt
+       if ! tar xf ../test.tar; then
+               error "Failed to untar archive on read-write mounted WIM"
+       fi
+       cd ..
+
+       # Diff the original tree with the mounted WIM
+       do_tree_cmp tmp.orig tmp.mnt
+
+       # Clear the mounted WIM and do it again!  (We need to test deleting
+       # stuff as well as creating stuff.)
+       if ! rm -rf tmp.mnt/*; then
+               error "Failed to clear mounted WIM"
+       fi
+
+       cd tmp.mnt
+       if ! tar xf ../test.tar; then
+               error "Failed to untar archive on read-write mounted WIM"
+       fi
+       cd ..
+
+       # Diff the original tree with the mounted WIM
+       do_tree_cmp tmp.orig tmp.mnt
+
+       # Unmount the WIM, apply it, and diff the original tree with the applied
+       # tree
+       if ! imagex unmount tmp.mnt --commit; then
+               error "Failed to unmount WIM mounted read-write"
+       fi
+       if ! imagex apply test.wim tmp.apply; then
+               error "Failed to apply WIM we previously had mounted read-write"
+       fi
+       do_tree_cmp tmp.orig tmp.apply
+       rm -rf tmp.orig/* tmp.apply/*
+}
+
+. common_tests.sh
+
+cleanup
+
+echo "**********************************************************"
+echo "                 WIM mount tests passed                   "
+echo "**********************************************************"
index 3b4d5a1454695123ffee4b72ff61b0011c99a47e..cf8b6d1b4361c46a53025b2f7a29e030c2c236e8 100755 (executable)
@@ -9,6 +9,7 @@
 # remain mounted.
 
 set -e
 # remain mounted.
 
 set -e
+srcdir=${srcdir:-.}
 srcdir=`realpath $srcdir`
 cd tests
 
 srcdir=`realpath $srcdir`
 cd tests
 
@@ -88,7 +89,7 @@ do_test() {
        if [ -x /usr/bin/tree ]; then
                tree in.mnt --inodes -F -s --noreport
        fi
        if [ -x /usr/bin/tree ]; then
                tree in.mnt --inodes -F -s --noreport
        fi
-       if ! ./ntfs-cmp in.mnt out.mnt; then
+       if ! ./tree-cmp in.mnt out.mnt NTFS; then
                if [ -x /usr/bin/tree ]; then
                        echo "Dumping tree of applied image"
                        tree out.mnt --inodes -F -s --noreport
                if [ -x /usr/bin/tree ]; then
                        echo "Dumping tree of applied image"
                        tree out.mnt --inodes -F -s --noreport
@@ -100,7 +101,9 @@ do_test() {
        __do_unmount out.mnt
 }
 msg() {
        __do_unmount out.mnt
 }
 msg() {
-       echo "Testing image capture and application of $1"
+       echo "--------------------------------------------------------------------"
+       echo "Testing image capture and application of NTFS volume containing $1"
+       echo "--------------------------------------------------------------------"
 }
 
 cleanup
 }
 
 cleanup
similarity index 80%
rename from tests/ntfs-cmp.c
rename to tests/tree-cmp.c
index 338dce56187a5af0efac07c211c8120514d185a6..a596962a45709822fc8ebba5dc6bc819743c31df 100644 (file)
@@ -1,5 +1,16 @@
 /* 
 /* 
- * A program to compare two mounted NTFS filesystems.
+ * A program to compare directory trees
+ *
+ * There are two modes:
+ *     - Normal mode for any filesystems.  We compare file names, contents,
+ *     sizes, modes, access times, and hard links.
+ *     - NTFS mode for NTFS-3g mounted volumes.  In this mode we need to
+ *       compare various NTFS-specific attributes such as named data streams
+ *       and DOS names.
+ *
+ * Both modes compare hard link groups between the two directory trees.  If two
+ * files are hard linked together in one directory tree, exactly the same two
+ * files are expected to be hard linked together in the other directory tree.
  */
 
 #include <stdarg.h>
  */
 
 #include <stdarg.h>
@@ -31,13 +42,14 @@ typedef uint64_t u64;
 #else
 #define DEBUG(format, ...)
 #endif
 #else
 #define DEBUG(format, ...)
 #endif
+static bool ntfs_mode = false;
 
 static void difference(const char *format, ...)
 {
        va_list va;
        va_start(va, format);
        fflush(stdout);
 
 static void difference(const char *format, ...)
 {
        va_list va;
        va_start(va, format);
        fflush(stdout);
-       fputs("ntfs-cmp: ", stderr);
+       fputs("tree-cmp: ", stderr);
        vfprintf(stderr, format, va);
        putc('\n', stderr);
        fflush(stderr);
        vfprintf(stderr, format, va);
        putc('\n', stderr);
        fflush(stderr);
@@ -51,7 +63,7 @@ static void error(const char *format, ...)
        int err = errno;
        va_start(va, format);
        fflush(stdout);
        int err = errno;
        va_start(va, format);
        fflush(stdout);
-       fputs("ntfs-cmp: ", stderr);
+       fputs("tree-cmp: ", stderr);
        vfprintf(stderr, format, va);
        fprintf(stderr, ": %s\n", strerror(err));
        va_end(va);
        vfprintf(stderr, format, va);
        fprintf(stderr, ": %s\n", strerror(err));
        va_end(va);
@@ -266,8 +278,8 @@ static void special_cmp(const char *file1, const char *file2)
 }
 
 
 }
 
 
-/* Compares file1 on one NTFS volume to file2 on another NTFS volume. */
-static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len)
+/* Recursively compares directory tree rooted at file1 to directory tree rooted at file2 */
+static void tree_cmp(char file1[], int file1_len, char file2[], int file2_len)
 {
        struct stat st1, st2;
        u64 ino_from, ino_to;
 {
        struct stat st1, st2;
        u64 ino_from, ino_to;
@@ -283,27 +295,30 @@ static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len)
                insert_ino(ino_from, st2.st_ino);
        else if (ino_to != st2.st_ino)
                difference("Inode number on `%s' is wrong", file2);
                insert_ino(ino_from, st2.st_ino);
        else if (ino_to != st2.st_ino)
                difference("Inode number on `%s' is wrong", file2);
-       if (st1.st_size != st2.st_size)
-               difference("Sizes of `%s' and `%s' are not the same",
-                          file1, file2);
-       if (st1.st_mode != st2.st_mode)
+       if ((st1.st_mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)) !=
+           (st2.st_mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)))
                difference("Modes of `%s' and `%s' are not the same",
                           file1, file2);
                difference("Modes of `%s' and `%s' are not the same",
                           file1, file2);
-       if (st1.st_atime != st2.st_atime)
+       if (S_ISREG(st1.st_mode) && st1.st_size != st2.st_size)
+               difference("Sizes of `%s' and `%s' are not the same",
+                          file1, file2);
+       if (ntfs_mode && st1.st_atime != st2.st_atime)
                difference("Access times of `%s' and `%s' are not the same",
                           file1, file2);
        if (st1.st_mtime != st2.st_mtime)
                difference("Access times of `%s' and `%s' are not the same",
                           file1, file2);
        if (st1.st_mtime != st2.st_mtime)
-               difference("Modification times times of `%s' and `%s' are not the same",
-                          file1, file2);
+               difference("Modification times of `%s' (%x) and `%s' (%x) are "
+                          "not the same",
+                          file1, st1.st_mtime, file2, st2.st_mtime);
 #if 0
        if (st1.st_ctime != st2.st_ctime)
                difference("Status change times of `%s' and `%s' are not the same",
                           file1, file2);
 #endif
 #if 0
        if (st1.st_ctime != st2.st_ctime)
                difference("Status change times of `%s' and `%s' are not the same",
                           file1, file2);
 #endif
-       if (st1.st_nlink != st2.st_nlink)
-               difference("Link count of `%s' and `%s' are not the same",
-                          file1, file2);
-       if (strcmp(file1, root1))
+       if ((ntfs_mode || S_ISREG(st1.st_mode)) && st1.st_nlink != st2.st_nlink)
+               difference("Link count of `%s' (%u) and `%s' (%u) "
+                          "are not the same",
+                          file1, st1.st_nlink, file2, st2.st_nlink);
+       if (ntfs_mode && strcmp(file1, root1) != 0)
                special_cmp(file1, file2);
        if (S_ISREG(st1.st_mode))
                cmp(file1, file2, st1.st_size);
                special_cmp(file1, file2);
        if (S_ISREG(st1.st_mode))
                cmp(file1, file2, st1.st_size);
@@ -343,7 +358,7 @@ static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len)
                        {
                                memcpy(file1 + file1_len + 1, name, name_len + 1);
                                memcpy(file2 + file2_len + 1, name, name_len + 1);
                        {
                                memcpy(file1 + file1_len + 1, name, name_len + 1);
                                memcpy(file2 + file2_len + 1, name, name_len + 1);
-                               ntfs_cmp(file1, file1_len + 1 + name_len,
+                               tree_cmp(file1, file1_len + 1 + name_len,
                                         file2, file2_len + 1 + name_len);
                        }
 
                                         file2, file2_len + 1 + name_len);
                        }
 
@@ -354,21 +369,36 @@ static void ntfs_cmp(char file1[], int file1_len, char file2[], int file2_len)
                free(namelist2);
                file1[file1_len] = '\0';
                file2[file2_len] = '\0';
                free(namelist2);
                file1[file1_len] = '\0';
                file2[file2_len] = '\0';
+       } else if (!ntfs_mode && S_ISLNK(st1.st_mode)) {
+               char buf1[4096], buf2[sizeof(buf1)];
+               ssize_t ret1, ret2;
+               ret1 = readlink(file1, buf1, sizeof(buf1));
+               if (ret1 == -1)
+                       error("Failed to get symlink target of `%s'", file1);
+               ret2 = readlink(file2, buf2, sizeof(buf2));
+               if (ret2 == -1)
+                       error("Failed to get symlink target of `%s'", file2);
+               if (ret1 != ret2 || memcmp(buf1, buf2, ret1))
+                       error("Symlink targets of `%s' and `%s' differ",
+                             file1, file2);
        }
 }
 
 int main(int argc, char **argv)
 {
        }
 }
 
 int main(int argc, char **argv)
 {
-       if (argc != 3) {
-               fprintf(stderr, "Usage: %s DIR1 DIR2", argv[0]);
+       if (argc != 3 && argc != 4) {
+               fprintf(stderr, "Usage: %s DIR1 DIR2 [NTFS]", argv[0]);
                return 2;
        }
                return 2;
        }
+       if (argc > 3 && strcmp(argv[3], "NTFS") == 0)
+               ntfs_mode = true;
+
        char dir1[4096];
        char dir2[4096];
        strcpy(dir1, argv[1]);
        strcpy(dir2, argv[2]);
        root1 = argv[1];
        root2 = argv[2];
        char dir1[4096];
        char dir2[4096];
        strcpy(dir1, argv[1]);
        strcpy(dir2, argv[2]);
        root1 = argv[1];
        root2 = argv[2];
-       ntfs_cmp(dir1, strlen(dir1), dir2, strlen(dir2));
+       tree_cmp(dir1, strlen(dir1), dir2, strlen(dir2));
        return 0;
 }
        return 0;
 }