From: Tim Kientzle Date: Wed, 9 Sep 2009 05:20:35 +0000 (-0400) Subject: Fix hardlink support on MinGW by dynamically loading X-Git-Tag: v2.8.0~364 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce5a2eedffba66fad43ae359987ed16123a5a77a;p=thirdparty%2Flibarchive.git Fix hardlink support on MinGW by dynamically loading the CreateHardLinkW function. This fixes the hardlink tests in libarchive_test on MinGW and VS9. SVN-Revision: 1444 --- diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index cd3a06733..305e38ad6 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -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); } diff --git a/libarchive/test/main.c b/libarchive/test/main.c index f43d5bd68..2248b375b 100644 --- a/libarchive/test/main.c +++ b/libarchive/test/main.c @@ -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);