Annotation of embedaddon/php/ext/fileinfo/libmagic/magic.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) Christos Zoulas 2003.
        !             3:  * All Rights Reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice immediately at the beginning of the file, without modification,
        !            10:  *    this list of conditions, and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            16:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            17:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            18:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
        !            19:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            25:  * SUCH DAMAGE.
        !            26:  */
        !            27: 
        !            28: #include "file.h"
        !            29: 
        !            30: #ifndef        lint
        !            31: FILE_RCSID("@(#)$File: magic.c,v 1.62 2009/03/20 21:25:41 christos Exp $")
        !            32: #endif /* lint */
        !            33: 
        !            34: #include "magic.h"
        !            35: 
        !            36: #include <stdlib.h>
        !            37: #ifdef PHP_WIN32
        !            38: #include "win32/unistd.h"
        !            39: #else
        !            40: #include <unistd.h>
        !            41: #endif
        !            42: #include <string.h>
        !            43: #ifdef PHP_WIN32
        !            44: # include "config.w32.h"
        !            45: #else
        !            46: # include "php_config.h"
        !            47: #endif
        !            48: 
        !            49: #include <limits.h>    /* for PIPE_BUF */
        !            50: 
        !            51: #if defined(HAVE_UTIMES)
        !            52: # include <sys/time.h>
        !            53: #elif defined(HAVE_UTIME)
        !            54: # if defined(HAVE_SYS_UTIME_H)
        !            55: #  include <sys/utime.h>
        !            56: # elif defined(HAVE_UTIME_H)
        !            57: #  include <utime.h>
        !            58: # endif
        !            59: #endif
        !            60: 
        !            61: #ifdef HAVE_UNISTD_H
        !            62: #include <unistd.h>    /* for read() */
        !            63: #endif
        !            64: 
        !            65: #ifndef PHP_WIN32
        !            66: # include <netinet/in.h>               /* for byte swapping */
        !            67: #endif
        !            68: 
        !            69: #include "patchlevel.h"
        !            70: 
        !            71: #ifndef PIPE_BUF
        !            72: /* Get the PIPE_BUF from pathconf */
        !            73: #ifdef _PC_PIPE_BUF
        !            74: #define PIPE_BUF pathconf(".", _PC_PIPE_BUF)
        !            75: #else
        !            76: #define PIPE_BUF 512
        !            77: #endif
        !            78: #endif
        !            79: 
        !            80: #ifdef PHP_WIN32
        !            81: # undef S_IFLNK
        !            82: # undef S_IFIFO
        !            83: #endif
        !            84: 
        !            85: private void free_mlist(struct mlist *);
        !            86: private void close_and_restore(const struct magic_set *, const char *, int,
        !            87:     const struct stat *);
        !            88: private int unreadable_info(struct magic_set *, mode_t, const char *);
        !            89: private const char *file_or_stream(struct magic_set *, const char *, php_stream *);
        !            90: 
        !            91: #ifndef        STDIN_FILENO
        !            92: #define        STDIN_FILENO    0
        !            93: #endif
        !            94: 
        !            95: public struct magic_set *
        !            96: magic_open(int flags)
        !            97: {
        !            98:        struct magic_set *ms;
        !            99: 
        !           100:        ms = ecalloc((size_t)1, sizeof(struct magic_set));
        !           101: 
        !           102:        if (magic_setflags(ms, flags) == -1) {
        !           103:                errno = EINVAL;
        !           104:                goto free;
        !           105:        }
        !           106: 
        !           107:        ms->o.buf = ms->o.pbuf = NULL;
        !           108: 
        !           109:        ms->c.li = emalloc((ms->c.len = 10) * sizeof(*ms->c.li));
        !           110:        
        !           111:        ms->event_flags = 0;
        !           112:        ms->error = -1;
        !           113:        ms->mlist = NULL;
        !           114:        ms->file = "unknown";
        !           115:        ms->line = 0;
        !           116:        return ms;
        !           117: free:
        !           118:        efree(ms);
        !           119:        return NULL;
        !           120: }
        !           121: 
        !           122: private void
        !           123: free_mlist(struct mlist *mlist)
        !           124: {
        !           125:        struct mlist *ml;
        !           126: 
        !           127:        if (mlist == NULL)
        !           128:                return;
        !           129: 
        !           130:        for (ml = mlist->next; ml != mlist;) {
        !           131:                struct mlist *next = ml->next;
        !           132:                struct magic *mg = ml->magic;
        !           133:                file_delmagic(mg, ml->mapped, ml->nmagic);
        !           134:                efree(ml);
        !           135:                ml = next;
        !           136:        }
        !           137:        efree(ml);
        !           138: }
        !           139: 
        !           140: private int
        !           141: unreadable_info(struct magic_set *ms, mode_t md, const char *file)
        !           142: {
        !           143:        /* We cannot open it, but we were able to stat it. */
        !           144:        if (access(file, W_OK) == 0)
        !           145:                if (file_printf(ms, "writable, ") == -1)
        !           146:                        return -1;
        !           147:        if (access(file, X_OK) == 0)
        !           148:                if (file_printf(ms, "executable, ") == -1)
        !           149:                        return -1;
        !           150:        if (S_ISREG(md))
        !           151:                if (file_printf(ms, "regular file, ") == -1)
        !           152:                        return -1;
        !           153:        if (file_printf(ms, "no read permission") == -1)
        !           154:                return -1;
        !           155:        return 0;
        !           156: }
        !           157: 
        !           158: public void
        !           159: magic_close(struct magic_set *ms)
        !           160: {
        !           161:        if (ms->mlist) {
        !           162:                free_mlist(ms->mlist);
        !           163:        }
        !           164:        if (ms->o.pbuf) {
        !           165:                efree(ms->o.pbuf);
        !           166:        }
        !           167:        if (ms->o.buf) {
        !           168:                efree(ms->o.buf);
        !           169:        }
        !           170:        if (ms->c.li) {
        !           171:                efree(ms->c.li);
        !           172:        }
        !           173:        efree(ms);
        !           174: }
        !           175: 
        !           176: /*
        !           177:  * load a magic file
        !           178:  */
        !           179: public int
        !           180: magic_load(struct magic_set *ms, const char *magicfile)
        !           181: {
        !           182:        struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD);
        !           183:        if (ml) {
        !           184:                free_mlist(ms->mlist);
        !           185:                ms->mlist = ml;
        !           186:                return 0;
        !           187:        }
        !           188:        return -1;
        !           189: }
        !           190: 
        !           191: public int
        !           192: magic_compile(struct magic_set *ms, const char *magicfile)
        !           193: {
        !           194:        struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE);
        !           195:        free_mlist(ml);
        !           196:        return ml ? 0 : -1;
        !           197: }
        !           198: 
        !           199: private void
        !           200: close_and_restore(const struct magic_set *ms, const char *name, int fd,
        !           201:     const struct stat *sb)
        !           202: {
        !           203: 
        !           204:        if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
        !           205:                /*
        !           206:                 * Try to restore access, modification times if read it.
        !           207:                 * This is really *bad* because it will modify the status
        !           208:                 * time of the file... And of course this will affect
        !           209:                 * backup programs
        !           210:                 */
        !           211: #ifdef HAVE_UTIMES
        !           212:                struct timeval  utsbuf[2];
        !           213:                (void)memset(utsbuf, 0, sizeof(utsbuf));
        !           214:                utsbuf[0].tv_sec = sb->st_atime;
        !           215:                utsbuf[1].tv_sec = sb->st_mtime;
        !           216: 
        !           217:                (void) utimes(name, utsbuf); /* don't care if loses */
        !           218: #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
        !           219:                struct utimbuf  utbuf;
        !           220: 
        !           221:                (void)memset(&utbuf, 0, sizeof(utbuf));
        !           222:                utbuf.actime = sb->st_atime;
        !           223:                utbuf.modtime = sb->st_mtime;
        !           224:                (void) utime(name, &utbuf); /* don't care if loses */
        !           225: #endif
        !           226:        }
        !           227: }
        !           228: 
        !           229: 
        !           230: /*
        !           231:  * find type of descriptor
        !           232:  */
        !           233: public const char *
        !           234: magic_descriptor(struct magic_set *ms, int fd)
        !           235: {
        !           236:        return file_or_stream(ms, NULL, NULL);
        !           237: }
        !           238: 
        !           239: /*
        !           240:  * find type of named file
        !           241:  */
        !           242: public const char *
        !           243: magic_file(struct magic_set *ms, const char *inname)
        !           244: {
        !           245:        return file_or_stream(ms, inname, NULL);
        !           246: }
        !           247: 
        !           248: public const char *
        !           249: magic_stream(struct magic_set *ms, php_stream *stream)
        !           250: {
        !           251:        return file_or_stream(ms, NULL, stream);
        !           252: }
        !           253: 
        !           254: private const char *
        !           255: file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
        !           256: {
        !           257:        int     rv = -1;
        !           258:        unsigned char *buf;
        !           259:        struct stat     sb;
        !           260:        ssize_t nbytes = 0;     /* number of bytes read from a datafile */
        !           261:        int no_in_stream = 0;
        !           262:        TSRMLS_FETCH();
        !           263: 
        !           264:        if (!inname && !stream) {
        !           265:                return NULL;
        !           266:        }
        !           267: 
        !           268:        /*
        !           269:         * one extra for terminating '\0', and
        !           270:         * some overlapping space for matches near EOF
        !           271:         */
        !           272: #define SLOP (1 + sizeof(union VALUETYPE))
        !           273:        buf = emalloc(HOWMANY + SLOP);
        !           274: 
        !           275:        if (file_reset(ms) == -1) {
        !           276:                goto done;
        !           277:        }
        !           278: 
        !           279:        switch (file_fsmagic(ms, inname, &sb, stream)) {
        !           280:                case -1:                /* error */
        !           281:                        goto done;
        !           282:                case 0:                 /* nothing found */
        !           283:                        break;
        !           284:                default:                /* matched it and printed type */
        !           285:                        rv = 0;
        !           286:                        goto done;
        !           287:        }
        !           288: 
        !           289:        errno = 0;
        !           290: 
        !           291:        if (!stream && inname) {
        !           292:                no_in_stream = 1;
        !           293: #if PHP_API_VERSION < 20100412
        !           294:                stream = php_stream_open_wrapper((char *)inname, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
        !           295: #else
        !           296:                stream = php_stream_open_wrapper((char *)inname, "rb", REPORT_ERRORS, NULL);
        !           297: #endif
        !           298:        }
        !           299: 
        !           300:        if (!stream) {
        !           301:                if (unreadable_info(ms, sb.st_mode, inname) == -1)
        !           302:                        goto done;
        !           303:                rv = 0;
        !           304:                goto done;
        !           305:        }
        !           306: 
        !           307: #ifdef O_NONBLOCK
        !           308: /* we should be already be in non blocking mode for network socket */
        !           309: #endif
        !           310: 
        !           311:        /*
        !           312:         * try looking at the first HOWMANY bytes
        !           313:         */
        !           314:        if ((nbytes = php_stream_read(stream, (char *)buf, HOWMANY)) < 0) {
        !           315:                file_error(ms, errno, "cannot read `%s'", inname);
        !           316:                goto done;
        !           317:        }
        !           318: 
        !           319:        (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
        !           320:        if (file_buffer(ms, stream, inname, buf, (size_t)nbytes) == -1)
        !           321:                goto done;
        !           322:        rv = 0;
        !           323: done:
        !           324:        efree(buf);
        !           325: 
        !           326:        if (no_in_stream && stream) {
        !           327:                php_stream_close(stream);
        !           328:        }
        !           329: 
        !           330:        close_and_restore(ms, inname, 0, &sb);
        !           331:        return rv == 0 ? file_getbuffer(ms) : NULL;
        !           332: }
        !           333: 
        !           334: public const char *
        !           335: magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
        !           336: {
        !           337:        if (file_reset(ms) == -1)
        !           338:                return NULL;
        !           339:        /*
        !           340:         * The main work is done here!
        !           341:         * We have the file name and/or the data buffer to be identified. 
        !           342:         */
        !           343:        if (file_buffer(ms, NULL, NULL, buf, nb) == -1) {
        !           344:                return NULL;
        !           345:        }
        !           346:        return file_getbuffer(ms);
        !           347: }
        !           348: 
        !           349: public const char *
        !           350: magic_error(struct magic_set *ms)
        !           351: {
        !           352:        return (ms->event_flags & EVENT_HAD_ERR) ? ms->o.buf : NULL;
        !           353: }
        !           354: 
        !           355: public int
        !           356: magic_errno(struct magic_set *ms)
        !           357: {
        !           358:        return (ms->event_flags & EVENT_HAD_ERR) ? ms->error : 0;
        !           359: }
        !           360: 
        !           361: public int
        !           362: magic_setflags(struct magic_set *ms, int flags)
        !           363: {
        !           364: #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
        !           365:        if (flags & MAGIC_PRESERVE_ATIME)
        !           366:                return -1;
        !           367: #endif
        !           368:        ms->flags = flags;
        !           369:        return 0;
        !           370: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>