]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Real hardlink detection on Windows (yes, Windows stat() really does seem to be that...
authorTim Kientzle <kientzle@gmail.com>
Fri, 11 Sep 2009 05:28:37 +0000 (01:28 -0400)
committerTim Kientzle <kientzle@gmail.com>
Fri, 11 Sep 2009 05:28:37 +0000 (01:28 -0400)
In particular, this fixes test_option_l on Windows.

SVN-Revision: 1452

cpio/test/main.c
cpio/test/test.h
cpio/test/test_option_l.c

index e8371b05a08b1ee49aac8b0b255c37cb0f333c61..6100ecceaae42463bb325487cac9a29be7589773 100644 (file)
@@ -133,6 +133,21 @@ my_CreateHardLinkA(const char *linkname, const char *target)
        }
        return f == NULL ? 0 : (*f)(linkname, target, NULL);
 }
+
+int
+my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
+{
+       HANDLE h;
+       int r;
+
+       h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
+               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+       if (h == INVALID_HANDLE_VALUE)
+               return (0);
+       r = GetFileInformationByHandle(h, bhfi);
+       CloseHandle(h);
+       return (r);
+}
 #endif
 
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
@@ -794,11 +809,32 @@ assertion_text_file_contents(const char *buff, const char *fn)
        return (0);
 }
 
-/* Verify that two paths point to the same file. */
+/* Test that two paths point to the same file. */
+/* As a side-effect, asserts that both files exist. */
 int
-assertion_file_hardlinks(const char *file, int line,
+is_file_hardlinks(const char *file, int line,
     const char *path1, const char *path2)
 {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2;
+       int r;
+
+       assertion_count(file, line);
+       r = my_GetFileInformationByName(path1, &bhfi1);
+       if (r == 0) {
+               failure_start(file, line, "File %s can't be inspected?", path1);
+               failure_finish(NULL);
+               return (0);
+       }
+       r = my_GetFileInformationByName(path2, &bhfi2);
+       if (r == 0) {
+               failure_start(file, line, "File %s can't be inspected?", path2);
+               failure_finish(NULL);
+               return (0);
+       }
+       return (bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh
+               && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow);
+#else
        struct stat st1, st2;
        int r;
 
@@ -815,13 +851,20 @@ assertion_file_hardlinks(const char *file, int line,
                failure_finish(NULL);
                return (0);
        }
-       if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
-               failure_start(file, line,
-                   "Files %s and %s are not hardlinked", path1, path2);
-               failure_finish(NULL);
-               return (0);
-       }
-       return (1);
+       return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev);
+#endif
+}
+
+int
+assertion_file_hardlinks(const char *file, int line,
+                                                const char *path1, const char *path2)
+{ 
+       if (is_file_hardlinks(file, line, path1, path2))
+               return (1);
+       failure_start(file, line,
+           "Files %s and %s are not hardlinked", path1, path2);
+       failure_finish(NULL);
+       return (0);
 }
 
 /* Verify a/b/mtime of 'pathname'. */
@@ -972,19 +1015,11 @@ assertion_file_nlinks(const char *file, int line,
     const char *pathname, int nlinks)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
-       HANDLE h;
        BY_HANDLE_FILE_INFORMATION bhfi;
        int r;
 
        assertion_count(file, line);
-       h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
-               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-       if (h == INVALID_HANDLE_VALUE) {
-               failure_start(file, line, "Can't access %s", pathname);
-               failure_finish(NULL);
-               return (0);
-       }
-       r = GetFileInformationByHandle(h, &bhfi);
+       r = my_GetFileInformationByName(pathname, &bhfi);
        if (r != 0 && bhfi.nNumberOfLinks == nlinks)
                return (1);
        failure_start(file, line, "File %s has %d links, expected %d",
index c9618134558b072d4b556747b992fe29af2143ee..5d89a45c406ff01287bc204c5238d0ca6d73add7 100644 (file)
 #define assertUmask(mask)      \
   assertion_umask(__FILE__, __LINE__, mask)
 
+/*
+ */
+#define isFileHardlinks(path1, path2)  \
+  is_file_hardlinks(__FILE__, __LINE__, path1, path2)
+
 /*
  * This would be simple with C99 variadic macros, but I don't want to
  * require that.  Instead, I insert a function call before each
@@ -238,6 +243,8 @@ int assertion_non_empty_file(const char *, ...);
 int assertion_text_file_contents(const char *buff, const char *f);
 int assertion_umask(const char *, int, int);
 void assertion_setup(const char *, int);
+
+int is_file_hardlinks(const char *, int, const char *, const char *);
 void test_skipping(const char *fmt, ...);
 
 /* Like sprintf, then system() */
index 81135d58d196e8e306213a42cf8afa3e640f0a78..f2cd5bfbf40c4ccd16a28e409ad552ee1872f1a1 100644 (file)
@@ -27,23 +27,18 @@ __FBSDID("$FreeBSD$");
 
 DEFINE_TEST(test_option_l)
 {
-       struct stat st, st2;
        int r;
 
        /* Create a file. */
        assertMakeFile("f", 0644, "a");
 
-       /* Stat it. */
-       assertEqualInt(0, stat("f", &st));
-
        /* Copy the file to the "copy" dir. */
        r = systemf("echo f | %s -pd copy >copy.out 2>copy.err",
            testprog);
        assertEqualInt(r, 0);
 
        /* Check that the copy is a true copy and not a link. */
-       assertEqualInt(0, stat("copy/f", &st2));
-       assert(st2.st_ino != st.st_ino);
+       assert(!isFileHardlinks("f", "copy/f"));
 
        /* Copy the file to the "link" dir with the -l option. */
        r = systemf("echo f | %s -pld link >link.out 2>link.err",
@@ -51,6 +46,5 @@ DEFINE_TEST(test_option_l)
        assertEqualInt(r, 0);
 
        /* Check that this is a link and not a copy. */
-       assertEqualInt(0, stat("link/f", &st2));
-       assert(st2.st_ino == st.st_ino);
+       assertFileHardlinks("f", "link/f");
 }