]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Fix hardlink support on MinGW by dynamically loading
authorTim Kientzle <kientzle@gmail.com>
Wed, 9 Sep 2009 05:20:35 +0000 (01:20 -0400)
committerTim Kientzle <kientzle@gmail.com>
Wed, 9 Sep 2009 05:20:35 +0000 (01:20 -0400)
the CreateHardLinkW function.  This fixes the hardlink
tests in libarchive_test on MinGW and VS9.

SVN-Revision: 1444

libarchive/archive_windows.c
libarchive/test/main.c

index cd3a067338862e63d304e22142c0f3eefc002396..305e38ad6be077cf11be300c74629afcf414837a 100644 (file)
@@ -218,7 +218,34 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
        return (handle);
 }
 
-#if HAVE_CREATEHARDLINKW
+static void *
+la_GetFunctionKernel32(const char *name)
+{
+       static HINSTANCE lib;
+       static int set;
+       if (!set) {
+               set = 1;
+               lib = LoadLibrary("kernel32.dll");
+       }
+       if (lib == NULL) {
+               fprintf(stderr, "Can't load kernel32.dll?!\n");
+               exit(1);
+       }
+       return (void *)GetProcAddress(lib, name);
+}
+
+static int
+la_CreateHardLinkW(wchar_t *linkname, wchar_t *target)
+{
+       static BOOLEAN (WINAPI *f)(LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES);
+       static int set;
+       if (!set) {
+               set = 1;
+               f = la_GetFunctionKernel32("CreateHardLinkW");
+       }
+       return f == NULL ? 0 : (*f)(linkname, target, NULL);
+}
+
 /* Check that path1 and path2 can be hard-linked by each other.
  * Both arguments must be made by permissive_name function. 
  */
@@ -298,7 +325,6 @@ canHardLinkW(const wchar_t *path1, const wchar_t *path2)
        else
                return (0);
 }
-#endif
 
 /* Make a link to src called dst.  */
 static int
@@ -330,12 +356,11 @@ __link(const char *src, const char *dst, int sym)
                        retval = -1;
                        goto exit;
                }
-#if HAVE_CREATEHARDLINKW
-               if (!sym && canHardLinkW(wsrc, wdst))
-                       res = CreateHardLinkW(wdst, wsrc, NULL);
-               else
-#endif
+               if (!sym && canHardLinkW(wsrc, wdst)) {
+                       res = la_CreateHardLinkW(wdst, wsrc);
+               } else {
                        res = CopyFileW(wsrc, wdst, FALSE);
+               }
        } else {
                /* wsrc does not exist; try src prepend it with the dirname of wdst */
                wchar_t *wnewsrc, *slash;
@@ -391,11 +416,9 @@ __link(const char *src, const char *dst, int sym)
                        retval = -1;
                        goto exit;
                }
-#if HAVE_CREATEHARDLINKW
                if (!sym && canHardLinkW(wnewsrc, wdst))
-                       res = CreateHardLinkW(wdst, wnewsrc, NULL);
+                       res = la_CreateHardLinkW(wdst, wnewsrc);
                else
-#endif
                        res = CopyFileW(wnewsrc, wdst, FALSE);
                free (wnewsrc);
        }
index f43d5bd683cd13f33053bbf2622d7cc96071fa25..2248b375b50118f27b9aab1e7b675aa268153fb9 100644 (file)
@@ -109,9 +109,10 @@ void *GetFunctionKernel32(const char *name)
        return (void *)GetProcAddress(lib, name);
 }
 
-int __CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
+static int
+my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
 {
-       static BOOLEAN (*f)(LPCSTR, LPCSTR, DWORD);
+       static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD);
        static int set;
        if (!set) {
                set = 1;
@@ -119,6 +120,18 @@ int __CreateSymbolicLinkA(const char *linkname, const char *target, int flags)
        }
        return f == NULL ? 0 : (*f)(linkname, target, flags);
 }
+
+static int
+my_CreateHardLinkA(const char *linkname, const char *target)
+{
+       static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
+       static int set;
+       if (!set) {
+               set = 1;
+               f = GetFunctionKernel32("CreateHardLinkA");
+       }
+       return f == NULL ? 0 : (*f)(linkname, target, NULL);
+}
 #endif
 
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
@@ -316,7 +329,7 @@ test_skipping(const char *fmt, ...)
        va_list ap;
 
        va_start(ap, fmt);
-       sprintf(buff, fmt, ap);
+       vsprintf(buff, fmt, ap);
        va_end(ap);
        /* failure_start() isn't quite right, but is awfully convenient. */
        failure_start(test_filename, test_line, "SKIPPING: %s", buff);
@@ -1197,10 +1210,10 @@ assertion_make_hardlink(const char *file, int line,
        int succeeded;
 
        assertion_count(file, line);
-#if HAVE_LINK
+#if defined(_WIN32) && !defined(__CYGWIN__)
+       succeeded = my_CreateHardLinkA(newpath, linkto);
+#elif HAVE_LINK
        succeeded = !link(linkto, newpath);
-#elif HAVE_CREATEHARDLINKA
-       succeeded = CreateHardLinkA(newpath, linkto, NULL);
 #else
        succeeded = 0;
 #endif
@@ -1221,7 +1234,7 @@ assertion_make_symlink(const char *file, int line,
 #if defined(_WIN32) && !defined(__CYGWIN__)
        int targetIsDir = 0;  /* TODO: Fix this */
        assertion_count(file, line);
-       if (__CreateSymbolicLinkA(newpath, linkto, targetIsDir))
+       if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir))
                return (1);
 #elif HAVE_SYMLINK
        assertion_count(file, line);