summaryrefslogtreecommitdiff
path: root/magic.c
diff options
context:
space:
mode:
authorDavid E. O'Brien <obrien@FreeBSD.org>2011-10-06 06:01:12 +0000
committerDavid E. O'Brien <obrien@FreeBSD.org>2011-10-06 06:01:12 +0000
commitdacc26abaa8ab61168c45f0716bea144fa8afd14 (patch)
treed25590ff6bfc3386fbca9494d26b8761e3d33410 /magic.c
parentb873e82fedb8026ff397a976c38d4182a21da706 (diff)
Notes
Diffstat (limited to 'magic.c')
-rw-r--r--magic.c147
1 files changed, 141 insertions, 6 deletions
diff --git a/magic.c b/magic.c
index b89989b338798..540395114f6b3 100644
--- a/magic.c
+++ b/magic.c
@@ -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;
}