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

Annotation of src/usr.bin/file/file.c, Revision 1.1

1.1     ! deraadt     1: /*
        !             2:  * file - find type of a file or files - main program.
        !             3:  *
        !             4:  * Copyright (c) Ian F. Darwin, 1987.
        !             5:  * Written by Ian F. Darwin.
        !             6:  *
        !             7:  * This software is not subject to any license of the American Telephone
        !             8:  * and Telegraph Company or of the Regents of the University of California.
        !             9:  *
        !            10:  * Permission is granted to anyone to use this software for any purpose on
        !            11:  * any computer system, and to alter it and redistribute it freely, subject
        !            12:  * to the following restrictions:
        !            13:  *
        !            14:  * 1. The author is not responsible for the consequences of use of this
        !            15:  *    software, no matter how awful, even if they arise from flaws in it.
        !            16:  *
        !            17:  * 2. The origin of this software must not be misrepresented, either by
        !            18:  *    explicit claim or by omission.  Since few users ever read sources,
        !            19:  *    credits must appear in the documentation.
        !            20:  *
        !            21:  * 3. Altered versions must be plainly marked as such, and must not be
        !            22:  *    misrepresented as being the original software.  Since few users
        !            23:  *    ever read sources, credits must appear in the documentation.
        !            24:  *
        !            25:  * 4. This notice may not be removed or altered.
        !            26:  */
        !            27: #ifndef        lint
        !            28: static char *moduleid =
        !            29:        "@(#)$Id: file.c,v 1.7 1995/07/13 13:22:58 mycroft Exp $";
        !            30: #endif /* lint */
        !            31:
        !            32: #include <stdio.h>
        !            33: #include <stdlib.h>
        !            34: #include <string.h>
        !            35: #include <sys/types.h>
        !            36: #include <sys/param.h> /* for MAXPATHLEN */
        !            37: #include <sys/stat.h>
        !            38: #include <fcntl.h>     /* for open() */
        !            39: #if (__COHERENT__ >= 0x420)
        !            40: #include <sys/utime.h>
        !            41: #else
        !            42: #include <utime.h>
        !            43: #endif
        !            44: #include <unistd.h>    /* for read() */
        !            45:
        !            46: #ifdef __ELF__
        !            47: #include <elf.h>
        !            48: #endif
        !            49:
        !            50: #include "patchlevel.h"
        !            51: #include "file.h"
        !            52:
        !            53: #ifdef S_IFLNK
        !            54: # define USAGE  "Usage: %s [-vczL] [-f namefile] [-m magicfile] file...\n"
        !            55: #else
        !            56: # define USAGE  "Usage: %s [-vcz] [-f namefile] [-m magicfile] file...\n"
        !            57: #endif
        !            58:
        !            59: #ifndef MAGIC
        !            60: # define MAGIC "/etc/magic"
        !            61: #endif
        !            62:
        !            63: int                    /* Global command-line options          */
        !            64:        debug = 0,      /* debugging                            */
        !            65:        lflag = 0,      /* follow Symlinks (BSD only)           */
        !            66:        zflag = 0;      /* follow (uncompress) compressed files */
        !            67:
        !            68: int                    /* Misc globals                         */
        !            69:        nmagic = 0;     /* number of valid magic[]s             */
        !            70:
        !            71: struct  magic *magic;  /* array of magic entries               */
        !            72:
        !            73: char *magicfile;       /* where magic be found                 */
        !            74:
        !            75: char *progname;                /* used throughout                      */
        !            76: int lineno;            /* line number in the magic file        */
        !            77:
        !            78:
        !            79: static void unwrap     __P((char *fn));
        !            80:
        !            81: /*
        !            82:  * main - parse arguments and handle options
        !            83:  */
        !            84: int
        !            85: main(argc, argv)
        !            86: int argc;
        !            87: char *argv[];
        !            88: {
        !            89:        int c;
        !            90:        int check = 0, didsomefiles = 0, errflg = 0, ret = 0, app = 0;
        !            91:
        !            92:        if ((progname = strrchr(argv[0], '/')) != NULL)
        !            93:                progname++;
        !            94:        else
        !            95:                progname = argv[0];
        !            96:
        !            97:        if (!(magicfile = getenv("MAGIC")))
        !            98:                magicfile = MAGIC;
        !            99:
        !           100:        while ((c = getopt(argc, argv, "vcdf:Lm:z")) != EOF)
        !           101:                switch (c) {
        !           102:                case 'v':
        !           103:                        (void) fprintf(stdout, "%s-%d.%d\n", progname,
        !           104:                                       FILE_VERSION_MAJOR, patchlevel);
        !           105:                        return 1;
        !           106:                case 'c':
        !           107:                        ++check;
        !           108:                        break;
        !           109:                case 'd':
        !           110:                        ++debug;
        !           111:                        break;
        !           112:                case 'f':
        !           113:                        if (!app) {
        !           114:                                ret = apprentice(magicfile, check);
        !           115:                                if (check)
        !           116:                                        exit(ret);
        !           117:                                app = 1;
        !           118:                        }
        !           119:                        unwrap(optarg);
        !           120:                        ++didsomefiles;
        !           121:                        break;
        !           122: #ifdef S_IFLNK
        !           123:                case 'L':
        !           124:                        ++lflag;
        !           125:                        break;
        !           126: #endif
        !           127:                case 'm':
        !           128:                        magicfile = optarg;
        !           129:                        break;
        !           130:                case 'z':
        !           131:                        zflag++;
        !           132:                        break;
        !           133:                case '?':
        !           134:                default:
        !           135:                        errflg++;
        !           136:                        break;
        !           137:                }
        !           138:
        !           139:        if (errflg) {
        !           140:                (void) fprintf(stderr, USAGE, progname);
        !           141:                exit(2);
        !           142:        }
        !           143:
        !           144:        if (!app) {
        !           145:                ret = apprentice(magicfile, check);
        !           146:                if (check)
        !           147:                        exit(ret);
        !           148:                app = 1;
        !           149:        }
        !           150:
        !           151:        if (optind == argc) {
        !           152:                if (!didsomefiles) {
        !           153:                        (void)fprintf(stderr, USAGE, progname);
        !           154:                        exit(2);
        !           155:                }
        !           156:        }
        !           157:        else {
        !           158:                int i, wid, nw;
        !           159:                for (wid = 0, i = optind; i < argc; i++) {
        !           160:                        nw = strlen(argv[i]);
        !           161:                        if (nw > wid)
        !           162:                                wid = nw;
        !           163:                }
        !           164:                for (; optind < argc; optind++)
        !           165:                        process(argv[optind], wid);
        !           166:        }
        !           167:
        !           168:        return 0;
        !           169: }
        !           170:
        !           171:
        !           172: /*
        !           173:  * unwrap -- read a file of filenames, do each one.
        !           174:  */
        !           175: static void
        !           176: unwrap(fn)
        !           177: char *fn;
        !           178: {
        !           179:        char buf[MAXPATHLEN];
        !           180:        FILE *f;
        !           181:        int wid = 0, cwid;
        !           182:
        !           183:        if ((f = fopen(fn, "r")) == NULL) {
        !           184:                error("Cannot open `%s' (%s).\n", fn, strerror(errno));
        !           185:                /*NOTREACHED*/
        !           186:        }
        !           187:
        !           188:        while (fgets(buf, MAXPATHLEN, f) != NULL) {
        !           189:                cwid = strlen(buf) - 1;
        !           190:                if (cwid > wid)
        !           191:                        wid = cwid;
        !           192:        }
        !           193:
        !           194:        rewind(f);
        !           195:
        !           196:        while (fgets(buf, MAXPATHLEN, f) != NULL) {
        !           197:                buf[strlen(buf)-1] = '\0';
        !           198:                process(buf, wid);
        !           199:        }
        !           200:
        !           201:        (void) fclose(f);
        !           202: }
        !           203:
        !           204:
        !           205: /*
        !           206:  * process - process input file
        !           207:  */
        !           208: void
        !           209: process(inname, wid)
        !           210: const char     *inname;
        !           211: int wid;
        !           212: {
        !           213:        int     fd = 0;
        !           214:        static  const char stdname[] = "standard input";
        !           215:        unsigned char   buf[HOWMANY+1]; /* one extra for terminating '\0' */
        !           216:        struct utimbuf  utbuf;
        !           217:        struct stat     sb;
        !           218:        int nbytes = 0; /* number of bytes read from a datafile */
        !           219:        char match = '\0';
        !           220:
        !           221:        if (strcmp("-", inname) == 0) {
        !           222:                if (fstat(0, &sb)<0) {
        !           223:                        error("cannot fstat `%s' (%s).\n", stdname,
        !           224:                              strerror(errno));
        !           225:                        /*NOTREACHED*/
        !           226:                }
        !           227:                inname = stdname;
        !           228:        }
        !           229:
        !           230:        if (wid > 0)
        !           231:             (void) printf("%s:%*s ", inname,
        !           232:                           (int) (wid - strlen(inname)), "");
        !           233:
        !           234:        if (inname != stdname) {
        !           235:            /*
        !           236:             * first try judging the file based on its filesystem status
        !           237:             */
        !           238:            if (fsmagic(inname, &sb) != 0) {
        !           239:                    putchar('\n');
        !           240:                    return;
        !           241:            }
        !           242:
        !           243:            if ((fd = open(inname, O_RDONLY)) < 0) {
        !           244:                    /* We can't open it, but we were able to stat it. */
        !           245:                    if (sb.st_mode & 0002) ckfputs("writeable, ", stdout);
        !           246:                    if (sb.st_mode & 0111) ckfputs("executable, ", stdout);
        !           247:                    ckfprintf(stdout, "can't read `%s' (%s).\n",
        !           248:                        inname, strerror(errno));
        !           249:                    return;
        !           250:            }
        !           251:        }
        !           252:
        !           253:
        !           254:        /*
        !           255:         * try looking at the first HOWMANY bytes
        !           256:         */
        !           257:        if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
        !           258:                error("read failed (%s).\n", strerror(errno));
        !           259:                /*NOTREACHED*/
        !           260:        }
        !           261:
        !           262:        if (nbytes == 0)
        !           263:                ckfputs("empty", stdout);
        !           264:        else {
        !           265:                buf[nbytes++] = '\0';   /* null-terminate it */
        !           266:                match = tryit(buf, nbytes, zflag);
        !           267:        }
        !           268: #ifdef __ELF__
        !           269:        /*
        !           270:         * ELF executables have multiple section headers in arbitrary
        !           271:         * file locations and thus file(1) cannot determine it from easily.
        !           272:         * Instead we traverse thru all section headers until a symbol table
        !           273:         * one is found or else the binary is stripped.
        !           274:         * XXX: This will not work for binaries of a different byteorder.
        !           275:         *      Should come up with a better fix.
        !           276:         */
        !           277:
        !           278:        if (match == 's' && nbytes > sizeof (Elf32_Ehdr) &&
        !           279:            buf[EI_MAG0] == ELFMAG0 &&
        !           280:            buf[EI_MAG1] == ELFMAG1 &&
        !           281:            buf[EI_MAG2] == ELFMAG2 &&
        !           282:            buf[EI_MAG3] == ELFMAG3) {
        !           283:
        !           284:                union {
        !           285:                        long l;
        !           286:                        char c[sizeof (long)];
        !           287:                } u;
        !           288:                Elf32_Ehdr elfhdr;
        !           289:                int stripped = 1;
        !           290:
        !           291:                u.l = 1;
        !           292:                (void) memcpy(&elfhdr, buf, sizeof elfhdr);
        !           293:
        !           294:                /*
        !           295:                 * If the system byteorder does not equal the object byteorder
        !           296:                 * then don't test.
        !           297:                 */
        !           298:                if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) {
        !           299:                    if (lseek(fd, elfhdr.e_shoff, SEEK_SET)<0)
        !           300:                        error("lseek failed (%s).\n", strerror(errno));
        !           301:
        !           302:                    for ( ; elfhdr.e_shnum ; elfhdr.e_shnum--) {
        !           303:                        if (read(fd, buf, elfhdr.e_shentsize)<0)
        !           304:                            error("read failed (%s).\n", strerror(errno));
        !           305:                        if (((Elf32_Shdr *)&buf)->sh_type == SHT_SYMTAB) {
        !           306:                            stripped = 0;
        !           307:                            break;
        !           308:                        }
        !           309:                    }
        !           310:                    if (stripped)
        !           311:                        (void) printf (", stripped");
        !           312:                }
        !           313:        }
        !           314: #endif
        !           315:
        !           316:        if (inname != stdname)
        !           317:                (void) close(fd);
        !           318:        (void) putchar('\n');
        !           319: }
        !           320:
        !           321:
        !           322: int
        !           323: tryit(buf, nb, zflag)
        !           324: unsigned char *buf;
        !           325: int nb, zflag;
        !           326: {
        !           327:        /* try compression stuff */
        !           328:        if (zflag && zmagic(buf, nb))
        !           329:                return 'z';
        !           330:
        !           331:        /* try tests in /etc/magic (or surrogate magic file) */
        !           332:        if (softmagic(buf, nb))
        !           333:                return 's';
        !           334:
        !           335:        /* try known keywords, check whether it is ASCII */
        !           336:        if (ascmagic(buf, nb))
        !           337:                return 'a';
        !           338:
        !           339:        /* abandon hope, all ye who remain here */
        !           340:        ckfputs("data", stdout);
        !           341:                return '\0';
        !           342: }