Annotation of embedaddon/php/ext/fileinfo/libmagic/magic.c, revision 1.1.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>