[BACK]Return to fsmagic.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / file

Annotation of src/usr.bin/file/fsmagic.c, Revision 1.14

1.14    ! deraadt     1: /*     $OpenBSD: fsmagic.c,v 1.13 2009/04/24 18:54:34 chl Exp $ */
1.1       deraadt     2: /*
1.7       ian         3:  * Copyright (c) Ian F. Darwin 1986-1995.
                      4:  * Software written by Ian F. Darwin and others;
                      5:  * maintained 1995-present by Christos Zoulas and others.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice immediately at the beginning of the file, without modification,
                     12:  *    this list of conditions, and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
                     21:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
1.1       deraadt    28:  */
1.10      tedu       29: /*
                     30:  * fsmagic - magic based on filesystem info - directory, special files, etc.
                     31:  */
1.1       deraadt    32:
1.10      tedu       33: #include "file.h"
                     34: #include "magic.h"
1.1       deraadt    35: #include <string.h>
1.10      tedu       36: #ifdef HAVE_UNISTD_H
1.1       deraadt    37: #include <unistd.h>
1.10      tedu       38: #endif
1.1       deraadt    39: #include <stdlib.h>
1.10      tedu       40: #include <sys/stat.h>
                     41: /* Since major is a function on SVR4, we cannot use `ifndef major'.  */
                     42: #ifdef MAJOR_IN_MKDEV
                     43: # include <sys/mkdev.h>
                     44: # define HAVE_MAJOR
                     45: #endif
                     46: #ifdef MAJOR_IN_SYSMACROS
                     47: # include <sys/sysmacros.h>
                     48: # define HAVE_MAJOR
                     49: #endif
                     50: #ifdef major                   /* Might be defined in sys/types.h.  */
                     51: # define HAVE_MAJOR
1.3       millert    52: #endif
1.10      tedu       53:
                     54: #ifndef HAVE_MAJOR
                     55: # define major(dev)  (((dev) >> 8) & 0xff)
                     56: # define minor(dev)  ((dev) & 0xff)
1.1       deraadt    57: #endif
1.10      tedu       58: #undef HAVE_MAJOR
1.1       deraadt    59:
1.13      chl        60: private int
                     61: bad_link(struct magic_set *ms, int err, char *buf)
                     62: {
                     63:        char *errfmt;
                     64:        if (err == ELOOP)
                     65:                errfmt = "symbolic link in a loop";
                     66:        else
                     67:                errfmt = "broken symbolic link to `%s'";
                     68:        if (ms->flags & MAGIC_ERROR) {
                     69:                file_error(ms, err, errfmt, buf);
                     70:                return -1;
                     71:        }
                     72:        if (file_printf(ms, errfmt, buf) == -1)
                     73:                return -1;
                     74:        return 1;
                     75: }
                     76:
1.10      tedu       77: protected int
                     78: file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
1.1       deraadt    79: {
                     80:        int ret = 0;
1.13      chl        81:        int mime = ms->flags & MAGIC_MIME;
1.10      tedu       82: #ifdef S_IFLNK
                     83:        char buf[BUFSIZ+4];
                     84:        int nch;
                     85:        struct stat tstatbuf;
                     86: #endif
                     87:
                     88:        if (fn == NULL)
                     89:                return 0;
1.1       deraadt    90:
                     91:        /*
                     92:         * Fstat is cheaper but fails for files you don't have read perms on.
                     93:         * On 4.2BSD and similar systems, use lstat() to identify symlinks.
                     94:         */
                     95: #ifdef S_IFLNK
1.10      tedu       96:        if ((ms->flags & MAGIC_SYMLINK) == 0)
1.1       deraadt    97:                ret = lstat(fn, sb);
                     98:        else
                     99: #endif
                    100:        ret = stat(fn, sb);     /* don't merge into if; see "ret =" above */
                    101:
                    102:        if (ret) {
1.10      tedu      103:                if (ms->flags & MAGIC_ERROR) {
                    104:                        file_error(ms, errno, "cannot stat `%s'", fn);
                    105:                        return -1;
                    106:                }
1.12      chl       107:                if (file_printf(ms, "cannot open `%s' (%s)",
                    108:                    fn, strerror(errno)) == -1)
1.10      tedu      109:                        return -1;
1.1       deraadt   110:                return 1;
                    111:        }
                    112:
1.13      chl       113:        if (mime) {
1.10      tedu      114:                if ((sb->st_mode & S_IFMT) != S_IFREG) {
1.13      chl       115:                        if ((mime & MAGIC_MIME_TYPE) &&
                    116:                            file_printf(ms, "application/x-not-regular-file")
1.10      tedu      117:                            == -1)
1.13      chl       118:                                    return -1;
1.10      tedu      119:                        return 1;
                    120:                }
                    121:        }
                    122:        else {
                    123: #ifdef S_ISUID
                    124:                if (sb->st_mode & S_ISUID)
                    125:                        if (file_printf(ms, "setuid ") == -1)
                    126:                                return -1;
                    127: #endif
                    128: #ifdef S_ISGID
                    129:                if (sb->st_mode & S_ISGID)
                    130:                        if (file_printf(ms, "setgid ") == -1)
                    131:                                return -1;
                    132: #endif
                    133: #ifdef S_ISVTX
                    134:                if (sb->st_mode & S_ISVTX)
                    135:                        if (file_printf(ms, "sticky ") == -1)
                    136:                                return -1;
                    137: #endif
                    138:        }
1.1       deraadt   139:
                    140:        switch (sb->st_mode & S_IFMT) {
                    141:        case S_IFDIR:
1.10      tedu      142:                if (file_printf(ms, "directory") == -1)
                    143:                        return -1;
1.1       deraadt   144:                return 1;
1.10      tedu      145: #ifdef S_IFCHR
1.1       deraadt   146:        case S_IFCHR:
1.10      tedu      147:                /*
                    148:                 * If -s has been specified, treat character special files
                    149:                 * like ordinary files.  Otherwise, just report that they
                    150:                 * are block special files and go on to the next file.
                    151:                 */
                    152:                if ((ms->flags & MAGIC_DEVICES) != 0)
                    153:                        break;
1.13      chl       154: #ifdef HAVE_STAT_ST_RDEV
1.10      tedu      155: # ifdef dv_unit
                    156:                if (file_printf(ms, "character special (%d/%d/%d)",
                    157:                    major(sb->st_rdev), dv_unit(sb->st_rdev),
                    158:                    dv_subunit(sb->st_rdev)) == -1)
                    159:                        return -1;
                    160: # else
                    161:                if (file_printf(ms, "character special (%ld/%ld)",
                    162:                    (long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1)
                    163:                        return -1;
                    164: # endif
                    165: #else
                    166:                if (file_printf(ms, "character special") == -1)
                    167:                        return -1;
                    168: #endif
1.1       deraadt   169:                return 1;
1.10      tedu      170: #endif
                    171: #ifdef S_IFBLK
1.1       deraadt   172:        case S_IFBLK:
1.10      tedu      173:                /*
                    174:                 * If -s has been specified, treat block special files
                    175:                 * like ordinary files.  Otherwise, just report that they
                    176:                 * are block special files and go on to the next file.
                    177:                 */
                    178:                if ((ms->flags & MAGIC_DEVICES) != 0)
                    179:                        break;
1.13      chl       180: #ifdef HAVE_STAT_ST_RDEV
1.10      tedu      181: # ifdef dv_unit
                    182:                if (file_printf(ms, "block special (%d/%d/%d)",
                    183:                    major(sb->st_rdev), dv_unit(sb->st_rdev),
                    184:                    dv_subunit(sb->st_rdev)) == -1)
                    185:                        return -1;
                    186: # else
                    187:                if (file_printf(ms, "block special (%ld/%ld)",
                    188:                    (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
                    189:                        return -1;
                    190: # endif
                    191: #else
                    192:                if (file_printf(ms, "block special") == -1)
                    193:                        return -1;
                    194: #endif
1.1       deraadt   195:                return 1;
1.10      tedu      196: #endif
1.1       deraadt   197:        /* TODO add code to handle V7 MUX and Blit MUX files */
                    198: #ifdef S_IFIFO
                    199:        case S_IFIFO:
1.12      chl       200:                if((ms->flags & MAGIC_DEVICES) != 0)
                    201:                        break;
1.10      tedu      202:                if (file_printf(ms, "fifo (named pipe)") == -1)
                    203:                        return -1;
                    204:                return 1;
                    205: #endif
                    206: #ifdef S_IFDOOR
                    207:        case S_IFDOOR:
                    208:                if (file_printf(ms, "door") == -1)
                    209:                        return -1;
1.1       deraadt   210:                return 1;
                    211: #endif
                    212: #ifdef S_IFLNK
                    213:        case S_IFLNK:
1.10      tedu      214:                if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
                    215:                        if (ms->flags & MAGIC_ERROR) {
                    216:                            file_error(ms, errno, "unreadable symlink `%s'",
                    217:                                fn);
                    218:                            return -1;
1.1       deraadt   219:                        }
1.10      tedu      220:                        if (file_printf(ms,
                    221:                            "unreadable symlink `%s' (%s)", fn,
                    222:                            strerror(errno)) == -1)
                    223:                                return -1;
                    224:                        return 1;
                    225:                }
1.13      chl       226:                buf[nch] = '\0';        /* readlink(2) does not do this */
1.1       deraadt   227:
1.10      tedu      228:                /* If broken symlink, say so and quit early. */
                    229:                if (*buf == '/') {
1.13      chl       230:                        if (stat(buf, &tstatbuf) < 0)
                    231:                                return bad_link(ms, errno, buf);
                    232:                } else {
1.10      tedu      233:                        char *tmp;
                    234:                        char buf2[BUFSIZ+BUFSIZ+4];
1.1       deraadt   235:
1.10      tedu      236:                        if ((tmp = strrchr(fn,  '/')) == NULL) {
1.1       deraadt   237:                                tmp = buf; /* in current directory anyway */
1.10      tedu      238:                        } else {
                    239:                                if (tmp - fn + 1 > BUFSIZ) {
                    240:                                        if (ms->flags & MAGIC_ERROR) {
                    241:                                                file_error(ms, 0,
                    242:                                                    "path too long: `%s'", buf);
                    243:                                                return -1;
                    244:                                        }
                    245:                                        if (file_printf(ms,
                    246:                                            "path too long: `%s'", fn) == -1)
                    247:                                                return -1;
                    248:                                        return 1;
                    249:                                }
                    250:                                (void)strlcpy(buf2, fn, sizeof buf2);  /* take dir part */
                    251:                                buf2[tmp - fn + 1] = '\0';
                    252:                                (void)strlcat(buf2, buf, sizeof buf2); /* plus (rel) link */
1.1       deraadt   253:                                tmp = buf2;
1.10      tedu      254:                        }
1.13      chl       255:                        if (stat(tmp, &tstatbuf) < 0)
                    256:                                return bad_link(ms, errno, buf);
1.10      tedu      257:                }
1.1       deraadt   258:
1.10      tedu      259:                /* Otherwise, handle it. */
                    260:                if ((ms->flags & MAGIC_SYMLINK) != 0) {
                    261:                        const char *p;
                    262:                        ms->flags &= MAGIC_SYMLINK;
                    263:                        p = magic_file(ms, buf);
                    264:                        ms->flags |= MAGIC_SYMLINK;
                    265:                        return p != NULL ? 1 : -1;
                    266:                } else { /* just print what it points to */
                    267:                        if (file_printf(ms, "symbolic link to `%s'",
                    268:                            buf) == -1)
                    269:                                return -1;
1.1       deraadt   270:                }
1.10      tedu      271:        return 1;
1.1       deraadt   272: #endif
                    273: #ifdef S_IFSOCK
                    274: #ifndef __COHERENT__
                    275:        case S_IFSOCK:
1.10      tedu      276:                if (file_printf(ms, "socket") == -1)
                    277:                        return -1;
1.1       deraadt   278:                return 1;
                    279: #endif
                    280: #endif
                    281:        case S_IFREG:
                    282:                break;
                    283:        default:
1.10      tedu      284:                file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
                    285:                return -1;
1.1       deraadt   286:                /*NOTREACHED*/
                    287:        }
                    288:
                    289:        /*
                    290:         * regular file, check next possibility
1.10      tedu      291:         *
                    292:         * If stat() tells us the file has zero length, report here that
                    293:         * the file is empty, so we can skip all the work of opening and
                    294:         * reading the file.
                    295:         * But if the -s option has been given, we skip this optimization,
                    296:         * since on some systems, stat() reports zero size for raw disk
                    297:         * partitions.  (If the block special device really has zero length,
                    298:         * the fact that it is empty will be detected and reported correctly
                    299:         * when we read the file.)
1.1       deraadt   300:         */
1.10      tedu      301:        if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
1.13      chl       302:                if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
                    303:                    file_printf(ms, mime ? "application/x-empty" :
                    304:                    "empty") == -1)
1.10      tedu      305:                        return -1;
1.1       deraadt   306:                return 1;
                    307:        }
                    308:        return 0;
                    309: }