diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2011-10-06 06:01:12 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2011-10-06 06:01:12 +0000 |
commit | dacc26abaa8ab61168c45f0716bea144fa8afd14 (patch) | |
tree | d25590ff6bfc3386fbca9494d26b8761e3d33410 /magic.c | |
parent | b873e82fedb8026ff397a976c38d4182a21da706 (diff) |
Notes
Diffstat (limited to 'magic.c')
-rw-r--r-- | magic.c | 147 |
1 files changed, 141 insertions, 6 deletions
@@ -25,10 +25,15 @@ * SUCH DAMAGE. */ +#ifdef WIN32 +#include <windows.h> +#include <shlwapi.h> +#endif + #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: magic.c,v 1.62 2009/03/20 21:25:41 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.74 2011/05/26 01:27:59 christos Exp $") #endif /* lint */ #include "magic.h" @@ -57,10 +62,6 @@ FILE_RCSID("@(#)$File: magic.c,v 1.62 2009/03/20 21:25:41 christos Exp $") #include <unistd.h> /* for read() */ #endif -#include <netinet/in.h> /* for byte swapping */ - -#include "patchlevel.h" - #ifndef PIPE_BUF /* Get the PIPE_BUF from pathconf */ #ifdef _PC_PIPE_BUF @@ -74,6 +75,7 @@ private void free_mlist(struct mlist *); private void close_and_restore(const struct magic_set *, const char *, int, const struct stat *); private int unreadable_info(struct magic_set *, mode_t, const char *); +private const char* get_default_magic(void); #ifndef COMPILE_ONLY private const char *file_or_fd(struct magic_set *, const char *, int); #endif @@ -82,13 +84,136 @@ private const char *file_or_fd(struct magic_set *, const char *, int); #define STDIN_FILENO 0 #endif +private const char * +get_default_magic(void) +{ + static const char hmagic[] = "/.magic/magic.mgc"; + static char *default_magic; + char *home, *hmagicpath; + +#ifndef WIN32 + struct stat st; + + if (default_magic) { + free(default_magic); + default_magic = NULL; + } + if ((home = getenv("HOME")) == NULL) + return MAGIC; + + if (asprintf(&hmagicpath, "%s/.magic", home) < 0) + return MAGIC; + if (stat(hmagicpath, &st) == -1) + goto out; + if (S_ISDIR(st.st_mode)) { + free(hmagicpath); + if (asprintf(&hmagicpath, "%s/%s", home, hmagic) < 0) + return MAGIC; + if (access(hmagicpath, R_OK) == -1) + goto out; + } + + if (asprintf(&default_magic, "%s:%s", hmagicpath, MAGIC) < 0) + goto out; + free(hmagicpath); + return default_magic; +out: + default_magic = NULL; + free(hmagicpath); + return MAGIC; +#else + char *hmagicp = hmagicpath; + char *tmppath = 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; + } + + APPENDPATH(); + + /* 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 magic file relative to dll location */ + LPTSTR 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(); + } + } + + /* Don't put MAGIC constant - it likely points to a file within MSys + tree */ + default_magic = hmagicpath; + return default_magic; +#endif +} + +public const char * +magic_getpath(const char *magicfile, int action) +{ + if (magicfile != NULL) + return magicfile; + + magicfile = getenv("MAGIC"); + if (magicfile != NULL) + return magicfile; + + return action == FILE_LOAD ? get_default_magic() : MAGIC; +} + public struct magic_set * magic_open(int flags) { struct magic_set *ms; size_t len; - if ((ms = CAST(magic_set *, calloc((size_t)1, + if ((ms = CAST(struct magic_set *, calloc((size_t)1, sizeof(struct magic_set)))) == NULL) return NULL; @@ -191,6 +316,14 @@ magic_check(struct magic_set *ms, const char *magicfile) return ml ? 0 : -1; } +public int +magic_list(struct magic_set *ms, const char *magicfile) +{ + struct mlist *ml = file_apprentice(ms, magicfile, FILE_LIST); + free_mlist(ml); + return ml ? 0 : -1; +} + private void close_and_restore(const struct magic_set *ms, const char *name, int fd, const struct stat *sb) @@ -281,7 +414,9 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) int flags = O_RDONLY|O_BINARY; if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) { +#ifdef O_NONBLOCK flags |= O_NONBLOCK; +#endif ispipe = 1; } |