[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.12

1.12    ! chl         1: /*     $OpenBSD: fsmagic.c,v 1.11 2005/05/18 03:11:18 jaredy 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:
                     60: #ifndef        lint
1.12    ! chl        61: FILE_RCSID("@(#)$Id: fsmagic.c,v 1.11 2005/05/18 03:11:18 jaredy Exp $")
1.1       deraadt    62: #endif /* lint */
                     63:
1.10      tedu       64: protected int
                     65: file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
1.1       deraadt    66: {
                     67:        int ret = 0;
1.10      tedu       68: #ifdef S_IFLNK
                     69:        char buf[BUFSIZ+4];
                     70:        int nch;
                     71:        struct stat tstatbuf;
                     72: #endif
                     73:
                     74:        if (fn == NULL)
                     75:                return 0;
1.1       deraadt    76:
                     77:        /*
                     78:         * Fstat is cheaper but fails for files you don't have read perms on.
                     79:         * On 4.2BSD and similar systems, use lstat() to identify symlinks.
                     80:         */
                     81: #ifdef S_IFLNK
1.10      tedu       82:        if ((ms->flags & MAGIC_SYMLINK) == 0)
1.1       deraadt    83:                ret = lstat(fn, sb);
                     84:        else
                     85: #endif
                     86:        ret = stat(fn, sb);     /* don't merge into if; see "ret =" above */
                     87:
                     88:        if (ret) {
1.10      tedu       89:                if (ms->flags & MAGIC_ERROR) {
                     90:                        file_error(ms, errno, "cannot stat `%s'", fn);
                     91:                        return -1;
                     92:                }
1.12    ! chl        93:                if (file_printf(ms, "cannot open `%s' (%s)",
        !            94:                    fn, strerror(errno)) == -1)
1.10      tedu       95:                        return -1;
1.1       deraadt    96:                return 1;
                     97:        }
                     98:
1.10      tedu       99:        if ((ms->flags & MAGIC_MIME) != 0) {
                    100:                if ((sb->st_mode & S_IFMT) != S_IFREG) {
                    101:                        if (file_printf(ms, "application/x-not-regular-file")
                    102:                            == -1)
                    103:                                return -1;
                    104:                        return 1;
                    105:                }
                    106:        }
                    107:        else {
                    108: #ifdef S_ISUID
                    109:                if (sb->st_mode & S_ISUID)
                    110:                        if (file_printf(ms, "setuid ") == -1)
                    111:                                return -1;
                    112: #endif
                    113: #ifdef S_ISGID
                    114:                if (sb->st_mode & S_ISGID)
                    115:                        if (file_printf(ms, "setgid ") == -1)
                    116:                                return -1;
                    117: #endif
                    118: #ifdef S_ISVTX
                    119:                if (sb->st_mode & S_ISVTX)
                    120:                        if (file_printf(ms, "sticky ") == -1)
                    121:                                return -1;
                    122: #endif
                    123:        }
1.1       deraadt   124:
                    125:        switch (sb->st_mode & S_IFMT) {
                    126:        case S_IFDIR:
1.10      tedu      127:                if (file_printf(ms, "directory") == -1)
                    128:                        return -1;
1.1       deraadt   129:                return 1;
1.10      tedu      130: #ifdef S_IFCHR
1.1       deraadt   131:        case S_IFCHR:
1.10      tedu      132:                /*
                    133:                 * If -s has been specified, treat character special files
                    134:                 * like ordinary files.  Otherwise, just report that they
                    135:                 * are block special files and go on to the next file.
                    136:                 */
                    137:                if ((ms->flags & MAGIC_DEVICES) != 0)
                    138:                        break;
                    139: #ifdef HAVE_ST_RDEV
                    140: # ifdef dv_unit
                    141:                if (file_printf(ms, "character special (%d/%d/%d)",
                    142:                    major(sb->st_rdev), dv_unit(sb->st_rdev),
                    143:                    dv_subunit(sb->st_rdev)) == -1)
                    144:                        return -1;
                    145: # else
                    146:                if (file_printf(ms, "character special (%ld/%ld)",
                    147:                    (long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1)
                    148:                        return -1;
                    149: # endif
                    150: #else
                    151:                if (file_printf(ms, "character special") == -1)
                    152:                        return -1;
                    153: #endif
1.1       deraadt   154:                return 1;
1.10      tedu      155: #endif
                    156: #ifdef S_IFBLK
1.1       deraadt   157:        case S_IFBLK:
1.10      tedu      158:                /*
                    159:                 * If -s has been specified, treat block special files
                    160:                 * like ordinary files.  Otherwise, just report that they
                    161:                 * are block special files and go on to the next file.
                    162:                 */
                    163:                if ((ms->flags & MAGIC_DEVICES) != 0)
                    164:                        break;
                    165: #ifdef HAVE_ST_RDEV
                    166: # ifdef dv_unit
                    167:                if (file_printf(ms, "block special (%d/%d/%d)",
                    168:                    major(sb->st_rdev), dv_unit(sb->st_rdev),
                    169:                    dv_subunit(sb->st_rdev)) == -1)
                    170:                        return -1;
                    171: # else
                    172:                if (file_printf(ms, "block special (%ld/%ld)",
                    173:                    (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
                    174:                        return -1;
                    175: # endif
                    176: #else
                    177:                if (file_printf(ms, "block special") == -1)
                    178:                        return -1;
                    179: #endif
1.1       deraadt   180:                return 1;
1.10      tedu      181: #endif
1.1       deraadt   182:        /* TODO add code to handle V7 MUX and Blit MUX files */
                    183: #ifdef S_IFIFO
                    184:        case S_IFIFO:
1.12    ! chl       185:                if((ms->flags & MAGIC_DEVICES) != 0)
        !           186:                        break;
1.10      tedu      187:                if (file_printf(ms, "fifo (named pipe)") == -1)
                    188:                        return -1;
                    189:                return 1;
                    190: #endif
                    191: #ifdef S_IFDOOR
                    192:        case S_IFDOOR:
                    193:                if (file_printf(ms, "door") == -1)
                    194:                        return -1;
1.1       deraadt   195:                return 1;
                    196: #endif
                    197: #ifdef S_IFLNK
                    198:        case S_IFLNK:
1.10      tedu      199:                if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
                    200:                        if (ms->flags & MAGIC_ERROR) {
                    201:                            file_error(ms, errno, "unreadable symlink `%s'",
                    202:                                fn);
                    203:                            return -1;
1.1       deraadt   204:                        }
1.10      tedu      205:                        if (file_printf(ms,
                    206:                            "unreadable symlink `%s' (%s)", fn,
                    207:                            strerror(errno)) == -1)
                    208:                                return -1;
                    209:                        return 1;
                    210:                }
                    211:                buf[nch] = '\0';        /* readlink(2) forgets this */
1.1       deraadt   212:
1.10      tedu      213:                /* If broken symlink, say so and quit early. */
                    214:                if (*buf == '/') {
                    215:                    if (stat(buf, &tstatbuf) < 0) {
                    216:                            if (ms->flags & MAGIC_ERROR) {
                    217:                                    file_error(ms, errno,
                    218:                                        "broken symbolic link to `%s'", buf);
                    219:                                    return -1;
                    220:                            }
                    221:                            if (file_printf(ms, "broken symbolic link to `%s'",
                    222:                                buf) == -1)
                    223:                                    return -1;
                    224:                            return 1;
                    225:                    }
                    226:                }
                    227:                else {
                    228:                        char *tmp;
                    229:                        char buf2[BUFSIZ+BUFSIZ+4];
1.1       deraadt   230:
1.10      tedu      231:                        if ((tmp = strrchr(fn,  '/')) == NULL) {
1.1       deraadt   232:                                tmp = buf; /* in current directory anyway */
1.10      tedu      233:                        } else {
                    234:                                if (tmp - fn + 1 > BUFSIZ) {
                    235:                                        if (ms->flags & MAGIC_ERROR) {
                    236:                                                file_error(ms, 0,
                    237:                                                    "path too long: `%s'", buf);
                    238:                                                return -1;
                    239:                                        }
                    240:                                        if (file_printf(ms,
                    241:                                            "path too long: `%s'", fn) == -1)
                    242:                                                return -1;
                    243:                                        return 1;
                    244:                                }
                    245:                                (void)strlcpy(buf2, fn, sizeof buf2);  /* take dir part */
                    246:                                buf2[tmp - fn + 1] = '\0';
                    247:                                (void)strlcat(buf2, buf, sizeof buf2); /* plus (rel) link */
1.1       deraadt   248:                                tmp = buf2;
1.10      tedu      249:                        }
                    250:                        if (stat(tmp, &tstatbuf) < 0) {
                    251:                                if (ms->flags & MAGIC_ERROR) {
                    252:                                        file_error(ms, errno,
                    253:                                            "broken symbolic link to `%s'",
                    254:                                            buf);
                    255:                                        return -1;
                    256:                                }
                    257:                                if (file_printf(ms,
                    258:                                    "broken symbolic link to `%s'", buf) == -1)
                    259:                                        return -1;
1.1       deraadt   260:                                return 1;
1.10      tedu      261:                        }
                    262:                }
1.1       deraadt   263:
1.10      tedu      264:                /* Otherwise, handle it. */
                    265:                if ((ms->flags & MAGIC_SYMLINK) != 0) {
                    266:                        const char *p;
                    267:                        ms->flags &= MAGIC_SYMLINK;
                    268:                        p = magic_file(ms, buf);
                    269:                        ms->flags |= MAGIC_SYMLINK;
                    270:                        return p != NULL ? 1 : -1;
                    271:                } else { /* just print what it points to */
                    272:                        if (file_printf(ms, "symbolic link to `%s'",
                    273:                            buf) == -1)
                    274:                                return -1;
1.1       deraadt   275:                }
1.10      tedu      276:        return 1;
1.1       deraadt   277: #endif
                    278: #ifdef S_IFSOCK
                    279: #ifndef __COHERENT__
                    280:        case S_IFSOCK:
1.10      tedu      281:                if (file_printf(ms, "socket") == -1)
                    282:                        return -1;
1.1       deraadt   283:                return 1;
                    284: #endif
                    285: #endif
                    286:        case S_IFREG:
                    287:                break;
                    288:        default:
1.10      tedu      289:                file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
                    290:                return -1;
1.1       deraadt   291:                /*NOTREACHED*/
                    292:        }
                    293:
                    294:        /*
                    295:         * regular file, check next possibility
1.10      tedu      296:         *
                    297:         * If stat() tells us the file has zero length, report here that
                    298:         * the file is empty, so we can skip all the work of opening and
                    299:         * reading the file.
                    300:         * But if the -s option has been given, we skip this optimization,
                    301:         * since on some systems, stat() reports zero size for raw disk
                    302:         * partitions.  (If the block special device really has zero length,
                    303:         * the fact that it is empty will be detected and reported correctly
                    304:         * when we read the file.)
1.1       deraadt   305:         */
1.10      tedu      306:        if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
                    307:                if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
                    308:                    "application/x-empty" : "empty") == -1)
                    309:                        return -1;
1.1       deraadt   310:                return 1;
                    311:        }
                    312:        return 0;
                    313: }