1284194Sdelphij/* 2284194Sdelphij * Copyright (c) Christos Zoulas 2003. 3284194Sdelphij * All Rights Reserved. 4284194Sdelphij * 5284194Sdelphij * Redistribution and use in source and binary forms, with or without 6284194Sdelphij * modification, are permitted provided that the following conditions 7284194Sdelphij * are met: 8284194Sdelphij * 1. Redistributions of source code must retain the above copyright 9284194Sdelphij * notice immediately at the beginning of the file, without modification, 10284194Sdelphij * this list of conditions, and the following disclaimer. 11284194Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 12284194Sdelphij * notice, this list of conditions and the following disclaimer in the 13284194Sdelphij * documentation and/or other materials provided with the distribution. 14284194Sdelphij * 15284194Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16284194Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17284194Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18284194Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19284194Sdelphij * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20284194Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21284194Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22284194Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23284194Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24284194Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25284194Sdelphij * SUCH DAMAGE. 26284194Sdelphij */ 27284194Sdelphij 28284194Sdelphij#ifdef WIN32 29284194Sdelphij#include <windows.h> 30284194Sdelphij#include <shlwapi.h> 31284194Sdelphij#endif 32284194Sdelphij 33284194Sdelphij#include "file.h" 34284194Sdelphij 35284194Sdelphij#ifndef lint 36284194SdelphijFILE_RCSID("@(#)$File: magic.c,v 1.91 2014/12/16 23:18:40 christos Exp $") 37284194Sdelphij#endif /* lint */ 38284194Sdelphij 39284194Sdelphij#include "magic.h" 40284194Sdelphij 41284194Sdelphij#include <stdlib.h> 42284194Sdelphij#include <unistd.h> 43284194Sdelphij#include <string.h> 44284194Sdelphij#ifdef QUICK 45284194Sdelphij#include <sys/mman.h> 46284194Sdelphij#endif 47284194Sdelphij#ifdef HAVE_LIMITS_H 48284194Sdelphij#include <limits.h> /* for PIPE_BUF */ 49284194Sdelphij#endif 50284194Sdelphij 51284194Sdelphij#if defined(HAVE_UTIMES) 52284194Sdelphij# include <sys/time.h> 53284194Sdelphij#elif defined(HAVE_UTIME) 54284194Sdelphij# if defined(HAVE_SYS_UTIME_H) 55284194Sdelphij# include <sys/utime.h> 56284194Sdelphij# elif defined(HAVE_UTIME_H) 57284194Sdelphij# include <utime.h> 58284194Sdelphij# endif 59284194Sdelphij#endif 60284194Sdelphij 61284194Sdelphij#ifdef HAVE_UNISTD_H 62284194Sdelphij#include <unistd.h> /* for read() */ 63284194Sdelphij#endif 64284194Sdelphij 65284194Sdelphij#ifndef PIPE_BUF 66284194Sdelphij/* Get the PIPE_BUF from pathconf */ 67284194Sdelphij#ifdef _PC_PIPE_BUF 68284194Sdelphij#define PIPE_BUF pathconf(".", _PC_PIPE_BUF) 69284194Sdelphij#else 70284194Sdelphij#define PIPE_BUF 512 71284194Sdelphij#endif 72284194Sdelphij#endif 73284194Sdelphij 74284194Sdelphijprivate void close_and_restore(const struct magic_set *, const char *, int, 75284194Sdelphij const struct stat *); 76284194Sdelphijprivate int unreadable_info(struct magic_set *, mode_t, const char *); 77284194Sdelphijprivate const char* get_default_magic(void); 78284194Sdelphij#ifndef COMPILE_ONLY 79284194Sdelphijprivate const char *file_or_fd(struct magic_set *, const char *, int); 80284194Sdelphij#endif 81284194Sdelphij 82284194Sdelphij#ifndef STDIN_FILENO 83284194Sdelphij#define STDIN_FILENO 0 84284194Sdelphij#endif 85284194Sdelphij 86284194Sdelphijprivate const char * 87284194Sdelphijget_default_magic(void) 88284194Sdelphij{ 89284194Sdelphij static const char hmagic[] = "/.magic/magic.mgc"; 90284194Sdelphij static char *default_magic; 91284194Sdelphij char *home, *hmagicpath; 92284194Sdelphij 93284194Sdelphij#ifndef WIN32 94284194Sdelphij struct stat st; 95284194Sdelphij 96284194Sdelphij if (default_magic) { 97284194Sdelphij free(default_magic); 98284194Sdelphij default_magic = NULL; 99284194Sdelphij } 100284194Sdelphij if ((home = getenv("HOME")) == NULL) 101284194Sdelphij return MAGIC; 102284194Sdelphij 103284194Sdelphij if (asprintf(&hmagicpath, "%s/.magic.mgc", home) < 0) 104284194Sdelphij return MAGIC; 105284194Sdelphij if (stat(hmagicpath, &st) == -1) { 106284194Sdelphij free(hmagicpath); 107284194Sdelphij if (asprintf(&hmagicpath, "%s/.magic", home) < 0) 108284194Sdelphij return MAGIC; 109284194Sdelphij if (stat(hmagicpath, &st) == -1) 110284194Sdelphij goto out; 111284194Sdelphij if (S_ISDIR(st.st_mode)) { 112284194Sdelphij free(hmagicpath); 113284194Sdelphij if (asprintf(&hmagicpath, "%s/%s", home, hmagic) < 0) 114284194Sdelphij return MAGIC; 115284194Sdelphij if (access(hmagicpath, R_OK) == -1) 116284194Sdelphij goto out; 117284194Sdelphij } 118284194Sdelphij } 119284194Sdelphij 120284194Sdelphij if (asprintf(&default_magic, "%s:%s", hmagicpath, MAGIC) < 0) 121284194Sdelphij goto out; 122284194Sdelphij free(hmagicpath); 123284194Sdelphij return default_magic; 124284194Sdelphijout: 125284194Sdelphij default_magic = NULL; 126284194Sdelphij free(hmagicpath); 127284194Sdelphij return MAGIC; 128284194Sdelphij#else 129284194Sdelphij char *hmagicp; 130284194Sdelphij char *tmppath = NULL; 131284194Sdelphij LPTSTR dllpath; 132284194Sdelphij hmagicpath = NULL; 133284194Sdelphij 134284194Sdelphij#define APPENDPATH() \ 135284194Sdelphij do { \ 136284194Sdelphij if (tmppath && access(tmppath, R_OK) != -1) { \ 137284194Sdelphij if (hmagicpath == NULL) \ 138284194Sdelphij hmagicpath = tmppath; \ 139284194Sdelphij else { \ 140284194Sdelphij if (asprintf(&hmagicp, "%s%c%s", hmagicpath, \ 141284194Sdelphij PATHSEP, tmppath) >= 0) { \ 142284194Sdelphij free(hmagicpath); \ 143284194Sdelphij hmagicpath = hmagicp; \ 144284194Sdelphij } \ 145284194Sdelphij free(tmppath); \ 146284194Sdelphij } \ 147284194Sdelphij tmppath = NULL; \ 148284194Sdelphij } \ 149284194Sdelphij } while (/*CONSTCOND*/0) 150284194Sdelphij 151284194Sdelphij if (default_magic) { 152284194Sdelphij free(default_magic); 153284194Sdelphij default_magic = NULL; 154284194Sdelphij } 155284194Sdelphij 156284194Sdelphij /* First, try to get user-specific magic file */ 157284194Sdelphij if ((home = getenv("LOCALAPPDATA")) == NULL) { 158284194Sdelphij if ((home = getenv("USERPROFILE")) != NULL) 159284194Sdelphij if (asprintf(&tmppath, 160284194Sdelphij "%s/Local Settings/Application Data%s", home, 161284194Sdelphij hmagic) < 0) 162284194Sdelphij tmppath = NULL; 163284194Sdelphij } else { 164284194Sdelphij if (asprintf(&tmppath, "%s%s", home, hmagic) < 0) 165284194Sdelphij tmppath = NULL; 166284194Sdelphij } 167284194Sdelphij 168284194Sdelphij APPENDPATH(); 169284194Sdelphij 170284194Sdelphij /* Second, try to get a magic file from Common Files */ 171284194Sdelphij if ((home = getenv("COMMONPROGRAMFILES")) != NULL) { 172284194Sdelphij if (asprintf(&tmppath, "%s%s", home, hmagic) >= 0) 173284194Sdelphij APPENDPATH(); 174284194Sdelphij } 175284194Sdelphij 176284194Sdelphij /* Third, try to get magic file relative to dll location */ 177284194Sdelphij dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1)); 178284194Sdelphij dllpath[MAX_PATH] = 0; /* just in case long path gets truncated and not null terminated */ 179284194Sdelphij if (GetModuleFileNameA(NULL, dllpath, MAX_PATH)){ 180284194Sdelphij PathRemoveFileSpecA(dllpath); 181284194Sdelphij if (strlen(dllpath) > 3 && 182284194Sdelphij stricmp(&dllpath[strlen(dllpath) - 3], "bin") == 0) { 183284194Sdelphij if (asprintf(&tmppath, 184284194Sdelphij "%s/../share/misc/magic.mgc", dllpath) >= 0) 185284194Sdelphij APPENDPATH(); 186284194Sdelphij } else { 187284194Sdelphij if (asprintf(&tmppath, 188284194Sdelphij "%s/share/misc/magic.mgc", dllpath) >= 0) 189284194Sdelphij APPENDPATH(); 190284194Sdelphij else if (asprintf(&tmppath, 191284194Sdelphij "%s/magic.mgc", dllpath) >= 0) 192284194Sdelphij APPENDPATH(); 193284194Sdelphij } 194284194Sdelphij } 195284194Sdelphij 196284194Sdelphij /* Don't put MAGIC constant - it likely points to a file within MSys 197284194Sdelphij tree */ 198284194Sdelphij default_magic = hmagicpath; 199284194Sdelphij return default_magic; 200284194Sdelphij#endif 201284194Sdelphij} 202284194Sdelphij 203284194Sdelphijpublic const char * 204284194Sdelphijmagic_getpath(const char *magicfile, int action) 205284194Sdelphij{ 206284194Sdelphij if (magicfile != NULL) 207284194Sdelphij return magicfile; 208284194Sdelphij 209284194Sdelphij magicfile = getenv("MAGIC"); 210284194Sdelphij if (magicfile != NULL) 211284194Sdelphij return magicfile; 212284194Sdelphij 213284194Sdelphij return action == FILE_LOAD ? get_default_magic() : MAGIC; 214284194Sdelphij} 215284194Sdelphij 216284194Sdelphijpublic struct magic_set * 217284194Sdelphijmagic_open(int flags) 218284194Sdelphij{ 219284194Sdelphij return file_ms_alloc(flags); 220284194Sdelphij} 221284194Sdelphij 222284194Sdelphijprivate int 223284194Sdelphijunreadable_info(struct magic_set *ms, mode_t md, const char *file) 224284194Sdelphij{ 225284194Sdelphij if (file) { 226284194Sdelphij /* We cannot open it, but we were able to stat it. */ 227284194Sdelphij if (access(file, W_OK) == 0) 228284194Sdelphij if (file_printf(ms, "writable, ") == -1) 229284194Sdelphij return -1; 230284194Sdelphij if (access(file, X_OK) == 0) 231284194Sdelphij if (file_printf(ms, "executable, ") == -1) 232284194Sdelphij return -1; 233284194Sdelphij } 234284194Sdelphij if (S_ISREG(md)) 235284194Sdelphij if (file_printf(ms, "regular file, ") == -1) 236284194Sdelphij return -1; 237284194Sdelphij if (file_printf(ms, "no read permission") == -1) 238284194Sdelphij return -1; 239284194Sdelphij return 0; 240284194Sdelphij} 241284194Sdelphij 242284194Sdelphijpublic void 243284194Sdelphijmagic_close(struct magic_set *ms) 244284194Sdelphij{ 245284194Sdelphij if (ms == NULL) 246284194Sdelphij return; 247284194Sdelphij file_ms_free(ms); 248284194Sdelphij} 249284194Sdelphij 250284194Sdelphij/* 251284194Sdelphij * load a magic file 252284194Sdelphij */ 253284194Sdelphijpublic int 254284194Sdelphijmagic_load(struct magic_set *ms, const char *magicfile) 255284194Sdelphij{ 256284194Sdelphij if (ms == NULL) 257284194Sdelphij return -1; 258284194Sdelphij return file_apprentice(ms, magicfile, FILE_LOAD); 259284194Sdelphij} 260284194Sdelphij 261284194Sdelphij#ifndef COMPILE_ONLY 262284194Sdelphij/* 263284194Sdelphij * Install a set of compiled magic buffers. 264284194Sdelphij */ 265284194Sdelphijpublic int 266284194Sdelphijmagic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes, 267284194Sdelphij size_t nbufs) 268284194Sdelphij{ 269284194Sdelphij if (ms == NULL) 270284194Sdelphij return -1; 271284194Sdelphij return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs); 272284194Sdelphij} 273284194Sdelphij#endif 274284194Sdelphij 275284194Sdelphijpublic int 276284194Sdelphijmagic_compile(struct magic_set *ms, const char *magicfile) 277284194Sdelphij{ 278284194Sdelphij if (ms == NULL) 279284194Sdelphij return -1; 280284194Sdelphij return file_apprentice(ms, magicfile, FILE_COMPILE); 281284194Sdelphij} 282284194Sdelphij 283284194Sdelphijpublic int 284284194Sdelphijmagic_check(struct magic_set *ms, const char *magicfile) 285284194Sdelphij{ 286284194Sdelphij if (ms == NULL) 287284194Sdelphij return -1; 288284194Sdelphij return file_apprentice(ms, magicfile, FILE_CHECK); 289284194Sdelphij} 290284194Sdelphij 291284194Sdelphijpublic int 292284194Sdelphijmagic_list(struct magic_set *ms, const char *magicfile) 293284194Sdelphij{ 294284194Sdelphij if (ms == NULL) 295284194Sdelphij return -1; 296284194Sdelphij return file_apprentice(ms, magicfile, FILE_LIST); 297284194Sdelphij} 298284194Sdelphij 299284194Sdelphijprivate void 300284194Sdelphijclose_and_restore(const struct magic_set *ms, const char *name, int fd, 301284194Sdelphij const struct stat *sb) 302284194Sdelphij{ 303284194Sdelphij if (fd == STDIN_FILENO || name == NULL) 304284194Sdelphij return; 305284194Sdelphij (void) close(fd); 306284194Sdelphij 307284194Sdelphij if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) { 308284194Sdelphij /* 309284194Sdelphij * Try to restore access, modification times if read it. 310284194Sdelphij * This is really *bad* because it will modify the status 311284194Sdelphij * time of the file... And of course this will affect 312284194Sdelphij * backup programs 313284194Sdelphij */ 314284194Sdelphij#ifdef HAVE_UTIMES 315284194Sdelphij struct timeval utsbuf[2]; 316284194Sdelphij (void)memset(utsbuf, 0, sizeof(utsbuf)); 317284194Sdelphij utsbuf[0].tv_sec = sb->st_atime; 318284194Sdelphij utsbuf[1].tv_sec = sb->st_mtime; 319284194Sdelphij 320284194Sdelphij (void) utimes(name, utsbuf); /* don't care if loses */ 321284194Sdelphij#elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H) 322284194Sdelphij struct utimbuf utbuf; 323284194Sdelphij 324284194Sdelphij (void)memset(&utbuf, 0, sizeof(utbuf)); 325284194Sdelphij utbuf.actime = sb->st_atime; 326284194Sdelphij utbuf.modtime = sb->st_mtime; 327284194Sdelphij (void) utime(name, &utbuf); /* don't care if loses */ 328284194Sdelphij#endif 329284194Sdelphij } 330284194Sdelphij} 331284194Sdelphij 332284194Sdelphij#ifndef COMPILE_ONLY 333284194Sdelphij 334284194Sdelphij/* 335284194Sdelphij * find type of descriptor 336284194Sdelphij */ 337284194Sdelphijpublic const char * 338284194Sdelphijmagic_descriptor(struct magic_set *ms, int fd) 339284194Sdelphij{ 340284194Sdelphij if (ms == NULL) 341284194Sdelphij return NULL; 342284194Sdelphij return file_or_fd(ms, NULL, fd); 343284194Sdelphij} 344284194Sdelphij 345284194Sdelphij/* 346284194Sdelphij * find type of named file 347284194Sdelphij */ 348284194Sdelphijpublic const char * 349284194Sdelphijmagic_file(struct magic_set *ms, const char *inname) 350284194Sdelphij{ 351284194Sdelphij if (ms == NULL) 352284194Sdelphij return NULL; 353284194Sdelphij return file_or_fd(ms, inname, STDIN_FILENO); 354284194Sdelphij} 355284194Sdelphij 356284194Sdelphijprivate const char * 357284194Sdelphijfile_or_fd(struct magic_set *ms, const char *inname, int fd) 358284194Sdelphij{ 359284194Sdelphij int rv = -1; 360284194Sdelphij unsigned char *buf; 361284194Sdelphij struct stat sb; 362284194Sdelphij ssize_t nbytes = 0; /* number of bytes read from a datafile */ 363284194Sdelphij int ispipe = 0; 364284194Sdelphij off_t pos = (off_t)-1; 365284194Sdelphij 366284194Sdelphij if (file_reset(ms) == -1) 367284194Sdelphij goto out; 368284194Sdelphij 369284194Sdelphij /* 370284194Sdelphij * one extra for terminating '\0', and 371284194Sdelphij * some overlapping space for matches near EOF 372284194Sdelphij */ 373284194Sdelphij#define SLOP (1 + sizeof(union VALUETYPE)) 374284194Sdelphij if ((buf = CAST(unsigned char *, malloc(HOWMANY + SLOP))) == NULL) 375284194Sdelphij return NULL; 376284194Sdelphij 377284194Sdelphij switch (file_fsmagic(ms, inname, &sb)) { 378284194Sdelphij case -1: /* error */ 379284194Sdelphij goto done; 380284194Sdelphij case 0: /* nothing found */ 381284194Sdelphij break; 382284194Sdelphij default: /* matched it and printed type */ 383284194Sdelphij rv = 0; 384284194Sdelphij goto done; 385284194Sdelphij } 386284194Sdelphij 387284194Sdelphij#ifdef WIN32 388284194Sdelphij /* Place stdin in binary mode, so EOF (Ctrl+Z) doesn't stop early. */ 389284194Sdelphij if (fd == STDIN_FILENO) 390284194Sdelphij _setmode(STDIN_FILENO, O_BINARY); 391284194Sdelphij#endif 392284194Sdelphij 393284194Sdelphij if (inname == NULL) { 394284194Sdelphij if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) 395284194Sdelphij ispipe = 1; 396284194Sdelphij else 397284194Sdelphij pos = lseek(fd, (off_t)0, SEEK_CUR); 398284194Sdelphij } else { 399284194Sdelphij int flags = O_RDONLY|O_BINARY; 400284194Sdelphij int okstat = stat(inname, &sb) == 0; 401284194Sdelphij 402284194Sdelphij if (okstat && S_ISFIFO(sb.st_mode)) { 403284194Sdelphij#ifdef O_NONBLOCK 404284194Sdelphij flags |= O_NONBLOCK; 405284194Sdelphij#endif 406284194Sdelphij ispipe = 1; 407284194Sdelphij } 408284194Sdelphij 409284194Sdelphij errno = 0; 410284194Sdelphij if ((fd = open(inname, flags)) < 0) { 411284194Sdelphij#ifdef WIN32 412284194Sdelphij /* 413284194Sdelphij * Can't stat, can't open. It may have been opened in 414284194Sdelphij * fsmagic, so if the user doesn't have read permission, 415284194Sdelphij * allow it to say so; otherwise an error was probably 416284194Sdelphij * displayed in fsmagic. 417284194Sdelphij */ 418284194Sdelphij if (!okstat && errno == EACCES) { 419284194Sdelphij sb.st_mode = S_IFBLK; 420284194Sdelphij okstat = 1; 421284194Sdelphij } 422284194Sdelphij#endif 423284194Sdelphij if (okstat && 424284194Sdelphij unreadable_info(ms, sb.st_mode, inname) == -1) 425284194Sdelphij goto done; 426284194Sdelphij rv = 0; 427284194Sdelphij goto done; 428284194Sdelphij } 429284194Sdelphij#ifdef O_NONBLOCK 430284194Sdelphij if ((flags = fcntl(fd, F_GETFL)) != -1) { 431284194Sdelphij flags &= ~O_NONBLOCK; 432284194Sdelphij (void)fcntl(fd, F_SETFL, flags); 433284194Sdelphij } 434284194Sdelphij#endif 435284194Sdelphij } 436284194Sdelphij 437284194Sdelphij /* 438284194Sdelphij * try looking at the first HOWMANY bytes 439284194Sdelphij */ 440284194Sdelphij if (ispipe) { 441284194Sdelphij ssize_t r = 0; 442284194Sdelphij 443284194Sdelphij while ((r = sread(fd, (void *)&buf[nbytes], 444284194Sdelphij (size_t)(HOWMANY - nbytes), 1)) > 0) { 445284194Sdelphij nbytes += r; 446284194Sdelphij if (r < PIPE_BUF) break; 447284194Sdelphij } 448284194Sdelphij 449284194Sdelphij if (nbytes == 0) { 450284194Sdelphij /* We can not read it, but we were able to stat it. */ 451284194Sdelphij if (unreadable_info(ms, sb.st_mode, inname) == -1) 452284194Sdelphij goto done; 453284194Sdelphij rv = 0; 454284194Sdelphij goto done; 455284194Sdelphij } 456284194Sdelphij 457284194Sdelphij } else { 458284194Sdelphij /* Windows refuses to read from a big console buffer. */ 459284194Sdelphij size_t howmany = 460284194Sdelphij#if defined(WIN32) && HOWMANY > 8 * 1024 461284194Sdelphij _isatty(fd) ? 8 * 1024 : 462284194Sdelphij#endif 463284194Sdelphij HOWMANY; 464284194Sdelphij if ((nbytes = read(fd, (char *)buf, howmany)) == -1) { 465284194Sdelphij if (inname == NULL && fd != STDIN_FILENO) 466284194Sdelphij file_error(ms, errno, "cannot read fd %d", fd); 467284194Sdelphij else 468284194Sdelphij file_error(ms, errno, "cannot read `%s'", 469284194Sdelphij inname == NULL ? "/dev/stdin" : inname); 470284194Sdelphij goto done; 471284194Sdelphij } 472284194Sdelphij } 473284194Sdelphij 474284194Sdelphij (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */ 475284194Sdelphij if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1) 476284194Sdelphij goto done; 477284194Sdelphij rv = 0; 478284194Sdelphijdone: 479284194Sdelphij free(buf); 480284194Sdelphij if (pos != (off_t)-1) 481284194Sdelphij (void)lseek(fd, pos, SEEK_SET); 482284194Sdelphij close_and_restore(ms, inname, fd, &sb); 483284194Sdelphijout: 484284194Sdelphij return rv == 0 ? file_getbuffer(ms) : NULL; 485284194Sdelphij} 486284194Sdelphij 487284194Sdelphij 488284194Sdelphijpublic const char * 489284194Sdelphijmagic_buffer(struct magic_set *ms, const void *buf, size_t nb) 490284194Sdelphij{ 491284194Sdelphij if (ms == NULL) 492284194Sdelphij return NULL; 493284194Sdelphij if (file_reset(ms) == -1) 494284194Sdelphij return NULL; 495284194Sdelphij /* 496284194Sdelphij * The main work is done here! 497284194Sdelphij * We have the file name and/or the data buffer to be identified. 498284194Sdelphij */ 499284194Sdelphij if (file_buffer(ms, -1, NULL, buf, nb) == -1) { 500284194Sdelphij return NULL; 501284194Sdelphij } 502284194Sdelphij return file_getbuffer(ms); 503284194Sdelphij} 504284194Sdelphij#endif 505284194Sdelphij 506284194Sdelphijpublic const char * 507284194Sdelphijmagic_error(struct magic_set *ms) 508284194Sdelphij{ 509284194Sdelphij if (ms == NULL) 510284194Sdelphij return "Magic database is not open"; 511284194Sdelphij return (ms->event_flags & EVENT_HAD_ERR) ? ms->o.buf : NULL; 512284194Sdelphij} 513284194Sdelphij 514284194Sdelphijpublic int 515284194Sdelphijmagic_errno(struct magic_set *ms) 516284194Sdelphij{ 517284194Sdelphij if (ms == NULL) 518284194Sdelphij return EINVAL; 519284194Sdelphij return (ms->event_flags & EVENT_HAD_ERR) ? ms->error : 0; 520284194Sdelphij} 521284194Sdelphij 522284194Sdelphijpublic int 523284194Sdelphijmagic_setflags(struct magic_set *ms, int flags) 524284194Sdelphij{ 525284194Sdelphij if (ms == NULL) 526284194Sdelphij return -1; 527284194Sdelphij#if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES) 528284194Sdelphij if (flags & MAGIC_PRESERVE_ATIME) 529284194Sdelphij return -1; 530284194Sdelphij#endif 531284194Sdelphij ms->flags = flags; 532284194Sdelphij return 0; 533284194Sdelphij} 534284194Sdelphij 535284194Sdelphijpublic int 536284194Sdelphijmagic_version(void) 537284194Sdelphij{ 538284194Sdelphij return MAGIC_VERSION; 539284194Sdelphij} 540284194Sdelphij 541284194Sdelphijpublic int 542284194Sdelphijmagic_setparam(struct magic_set *ms, int param, const void *val) 543284194Sdelphij{ 544284194Sdelphij switch (param) { 545284194Sdelphij case MAGIC_PARAM_INDIR_MAX: 546284194Sdelphij ms->indir_max = *(const size_t *)val; 547284194Sdelphij return 0; 548284194Sdelphij case MAGIC_PARAM_NAME_MAX: 549284194Sdelphij ms->name_max = *(const size_t *)val; 550284194Sdelphij return 0; 551284194Sdelphij case MAGIC_PARAM_ELF_PHNUM_MAX: 552284194Sdelphij ms->elf_phnum_max = *(const size_t *)val; 553284194Sdelphij return 0; 554284194Sdelphij case MAGIC_PARAM_ELF_SHNUM_MAX: 555284194Sdelphij ms->elf_shnum_max = *(const size_t *)val; 556284194Sdelphij return 0; 557284194Sdelphij case MAGIC_PARAM_ELF_NOTES_MAX: 558284194Sdelphij ms->elf_notes_max = *(const size_t *)val; 559284194Sdelphij return 0; 560284194Sdelphij default: 561284194Sdelphij errno = EINVAL; 562284194Sdelphij return -1; 563284194Sdelphij } 564284194Sdelphij} 565284194Sdelphij 566284194Sdelphijpublic int 567284194Sdelphijmagic_getparam(struct magic_set *ms, int param, void *val) 568284194Sdelphij{ 569284194Sdelphij switch (param) { 570284194Sdelphij case MAGIC_PARAM_INDIR_MAX: 571284194Sdelphij *(size_t *)val = ms->indir_max; 572284194Sdelphij return 0; 573284194Sdelphij case MAGIC_PARAM_NAME_MAX: 574284194Sdelphij *(size_t *)val = ms->name_max; 575284194Sdelphij return 0; 576284194Sdelphij case MAGIC_PARAM_ELF_PHNUM_MAX: 577284194Sdelphij *(size_t *)val = ms->elf_phnum_max; 578284194Sdelphij return 0; 579284194Sdelphij case MAGIC_PARAM_ELF_SHNUM_MAX: 580284194Sdelphij *(size_t *)val = ms->elf_shnum_max; 581284194Sdelphij return 0; 582284194Sdelphij case MAGIC_PARAM_ELF_NOTES_MAX: 583284194Sdelphij *(size_t *)val = ms->elf_notes_max; 584284194Sdelphij return 0; 585284194Sdelphij default: 586284194Sdelphij errno = EINVAL; 587284194Sdelphij return -1; 588284194Sdelphij } 589284194Sdelphij} 590