From d9aa254e0212d7d674b0c7f9259a15bd2f33d2d3 Mon Sep 17 00:00:00 2001 From: Christos Zoulas Date: Wed, 15 Apr 2015 23:47:58 +0000 Subject: [PATCH] Restructure and clarify the windows magic file search. (from LRN) --- src/magic.c | 156 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 59 deletions(-) diff --git a/src/magic.c b/src/magic.c index c8044ed3..c779f5c3 100644 --- a/src/magic.c +++ b/src/magic.c @@ -33,7 +33,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: magic.c,v 1.91 2014/12/16 23:18:40 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.92 2015/01/02 21:29:39 christos Exp $") #endif /* lint */ #include "magic.h" @@ -83,6 +83,86 @@ private const char *file_or_fd(struct magic_set *, const char *, int); #define STDIN_FILENO 0 #endif +#ifdef WIN32 +/* HINSTANCE of this shared library. Needed for get_default_magic() */ +static HINSTANCE _w32_dll_instance = NULL; + +static void +_w32_append_path(char **hmagicpath, const char *fmt, ...) +{ + char *tmppath; + char *newpath; + va_list ap; + + va_start(ap, fmt); + if (vasprintf(&tmppath, fmt, ap) < 0) { + va_end(ap); + return; + } + va_end(ap); + + if (access(tmppath, R_OK) == -1) + goto out; + + if (*hmagicpath == NULL) { + *hmagicpath = tmppath; + return; + } + + if (asprintf(&newpath, "%s%c%s", *hmagicpath, PATHSEP, tmppath) < 0) + goto out; + + free(*hmagicpath); + free(tmppath); + *hmagicpath = newpath; + return; +out: + free(tmppath); +} + +static void +_w32_get_magic_relative_to(char **hmagicpath, HINSTANCE module) +{ + static const char *trypaths[] = { + "%s/share/misc/magic.mgc", + "%s/magic.mgc", + }; + LPSTR dllpath; + size_t sp; + + dllpath = calloc(MAX_PATH + 1, sizeof(*dllpath)); + + if (!GetModuleFileNameA(module, dllpath, MAX_PATH)) + goto out; + + PathRemoveFileSpecA(dllpath); + + sp = strlen(dllpath); + if (sp > 3 && stricmp(&dllpath[sp - 3], "bin") == 0) { + _w32_append_path(hmagicpath, + "%s/../share/misc/magic.mgc", dllpath); + goto out; + } + + for (sp = 0; sp < __arraycount(trypaths); sp++) + _w32_append_path(hmagicpath, trypaths[sp], dllpath); +out: + free(dllpath); +} + +/* Placate GCC by offering a sacrificial previous prototype */ +BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID); + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, + LPVOID lpvReserved __attribute__((__unused__))) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + _w32_dll_instance = hinstDLL; + return TRUE; +} +#endif + private const char * get_default_magic(void) { @@ -126,75 +206,33 @@ out: free(hmagicpath); return MAGIC; #else - char *hmagicp; - char *tmppath = NULL; - LPTSTR dllpath; hmagicpath = NULL; -#define APPENDPATH() \ - do { \ - if (tmppath && access(tmppath, R_OK) != -1) { \ - if (hmagicpath == NULL) \ - hmagicpath = tmppath; \ - else { \ - if (asprintf(&hmagicp, "%s%c%s", hmagicpath, \ - PATHSEP, tmppath) >= 0) { \ - free(hmagicpath); \ - hmagicpath = hmagicp; \ - } \ - free(tmppath); \ - } \ - tmppath = NULL; \ - } \ - } while (/*CONSTCOND*/0) - if (default_magic) { free(default_magic); default_magic = NULL; } - /* First, try to get user-specific magic file */ - if ((home = getenv("LOCALAPPDATA")) == NULL) { - if ((home = getenv("USERPROFILE")) != NULL) - if (asprintf(&tmppath, - "%s/Local Settings/Application Data%s", home, - hmagic) < 0) - tmppath = NULL; - } else { - if (asprintf(&tmppath, "%s%s", home, hmagic) < 0) - tmppath = NULL; - } + /* First, try to get a magic file from user-application data */ + if ((home = getenv("LOCALAPPDATA")) != NULL) + _w32_append_path(&hmagicpath, "%s%s", home, hmagic); - APPENDPATH(); + /* Second, try to get a magic file from the user profile data */ + if ((home = getenv("USERPROFILE")) != NULL) + _w32_append_path(&hmagicpath, + "%s/Local Settings/Application Data%s", home, hmagic); - /* Second, try to get a magic file from Common Files */ - if ((home = getenv("COMMONPROGRAMFILES")) != NULL) { - if (asprintf(&tmppath, "%s%s", home, hmagic) >= 0) - APPENDPATH(); - } + /* Third, try to get a magic file from Common Files */ + if ((home = getenv("COMMONPROGRAMFILES")) != NULL) + _w32_append_path(&hmagicpath, "%s%s", home, hmagic); - /* Third, try to get magic file relative to dll location */ - dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1)); - dllpath[MAX_PATH] = 0; /* just in case long path gets truncated and not null terminated */ - if (GetModuleFileNameA(NULL, dllpath, MAX_PATH)){ - PathRemoveFileSpecA(dllpath); - if (strlen(dllpath) > 3 && - stricmp(&dllpath[strlen(dllpath) - 3], "bin") == 0) { - if (asprintf(&tmppath, - "%s/../share/misc/magic.mgc", dllpath) >= 0) - APPENDPATH(); - } else { - if (asprintf(&tmppath, - "%s/share/misc/magic.mgc", dllpath) >= 0) - APPENDPATH(); - else if (asprintf(&tmppath, - "%s/magic.mgc", dllpath) >= 0) - APPENDPATH(); - } - } + /* Fourth, try to get magic file relative to exe location */ + _w32_get_magic_relative_to(&hmagicpath, NULL); + + /* Fifth, try to get magic file relative to dll location */ + _w32_get_magic_relative_to(&hmagicpath, _w32_dll_instance); - /* Don't put MAGIC constant - it likely points to a file within MSys - tree */ + /* Avoid MAGIC constant - it likely points to a file within MSys tree */ default_magic = hmagicpath; return default_magic; #endif -- 2.40.0