]> granicus.if.org Git - file/commitdiff
Restructure and clarify the windows magic file search. (from LRN)
authorChristos Zoulas <christos@zoulas.com>
Wed, 15 Apr 2015 23:47:58 +0000 (23:47 +0000)
committerChristos Zoulas <christos@zoulas.com>
Wed, 15 Apr 2015 23:47:58 +0000 (23:47 +0000)
src/magic.c

index c8044ed3548884b93df3db8b975a2a043eccb1f5..c779f5c3aabcae3419eeec9cd3218cf413da8fcb 100644 (file)
@@ -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