Annotation of src/usr.bin/file/fsmagic.c, Revision 1.1
1.1 ! deraadt 1: /*
! 2: * fsmagic - magic based on filesystem info - directory, special files, etc.
! 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:
! 28: #include <stdio.h>
! 29: #include <string.h>
! 30: #include <sys/types.h>
! 31: #include <sys/stat.h>
! 32: #include <unistd.h>
! 33: #include <stdlib.h>
! 34: #ifndef major /* if `major' not defined in types.h, */
! 35: #include <sys/sysmacros.h> /* try this one. */
! 36: #endif
! 37: #ifndef major /* still not defined? give up, manual intervention needed */
! 38: /* If cc tries to compile this, read and act on it. */
! 39: /* On most systems cpp will discard it automatically */
! 40: Congratulations, you have found a portability bug.
! 41: Please grep /usr/include/sys and edit the above #include
! 42: to point at the file that defines the "major" macro.
! 43: #endif /*major*/
! 44:
! 45: #include "file.h"
! 46:
! 47: #ifndef lint
! 48: static char *moduleid =
! 49: "@(#)$Id: fsmagic.c,v 1.7 1995/04/28 19:23:51 christos Exp $";
! 50: #endif /* lint */
! 51:
! 52: int
! 53: fsmagic(fn, sb)
! 54: const char *fn;
! 55: struct stat *sb;
! 56: {
! 57: int ret = 0;
! 58:
! 59: /*
! 60: * Fstat is cheaper but fails for files you don't have read perms on.
! 61: * On 4.2BSD and similar systems, use lstat() to identify symlinks.
! 62: */
! 63: #ifdef S_IFLNK
! 64: if (!lflag)
! 65: ret = lstat(fn, sb);
! 66: else
! 67: #endif
! 68: ret = stat(fn, sb); /* don't merge into if; see "ret =" above */
! 69:
! 70: if (ret) {
! 71: ckfprintf(stdout,
! 72: /* Yes, I do mean stdout. */
! 73: /* No \n, caller will provide. */
! 74: "can't stat `%s' (%s).", fn, strerror(errno));
! 75: return 1;
! 76: }
! 77:
! 78: if (sb->st_mode & S_ISUID) ckfputs("setuid ", stdout);
! 79: if (sb->st_mode & S_ISGID) ckfputs("setgid ", stdout);
! 80: if (sb->st_mode & S_ISVTX) ckfputs("sticky ", stdout);
! 81:
! 82: switch (sb->st_mode & S_IFMT) {
! 83: case S_IFDIR:
! 84: ckfputs("directory", stdout);
! 85: return 1;
! 86: case S_IFCHR:
! 87: (void) printf("character special (%d/%d)",
! 88: major(sb->st_rdev), minor(sb->st_rdev));
! 89: return 1;
! 90: case S_IFBLK:
! 91: (void) printf("block special (%d/%d)",
! 92: major(sb->st_rdev), minor(sb->st_rdev));
! 93: return 1;
! 94: /* TODO add code to handle V7 MUX and Blit MUX files */
! 95: #ifdef S_IFIFO
! 96: case S_IFIFO:
! 97: ckfputs("fifo (named pipe)", stdout);
! 98: return 1;
! 99: #endif
! 100: #ifdef S_IFLNK
! 101: case S_IFLNK:
! 102: {
! 103: char buf[BUFSIZ+4];
! 104: register int nch;
! 105: struct stat tstatbuf;
! 106:
! 107: if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
! 108: ckfprintf(stdout, "unreadable symlink (%s).",
! 109: strerror(errno));
! 110: return 1;
! 111: }
! 112: buf[nch] = '\0'; /* readlink(2) forgets this */
! 113:
! 114: /* If broken symlink, say so and quit early. */
! 115: if (*buf == '/') {
! 116: if (stat(buf, &tstatbuf) < 0) {
! 117: ckfprintf(stdout,
! 118: "broken symbolic link to %s", buf);
! 119: return 1;
! 120: }
! 121: }
! 122: else {
! 123: char *tmp;
! 124: char buf2[BUFSIZ+BUFSIZ+4];
! 125:
! 126: if ((tmp = strrchr(fn, '/')) == NULL) {
! 127: tmp = buf; /* in current directory anyway */
! 128: }
! 129: else {
! 130: strcpy (buf2, fn); /* take directory part */
! 131: buf2[tmp-fn+1] = '\0';
! 132: strcat (buf2, buf); /* plus (relative) symlink */
! 133: tmp = buf2;
! 134: }
! 135: if (stat(tmp, &tstatbuf) < 0) {
! 136: ckfprintf(stdout,
! 137: "broken symbolic link to %s", buf);
! 138: return 1;
! 139: }
! 140: }
! 141:
! 142: /* Otherwise, handle it. */
! 143: if (lflag) {
! 144: process(buf, strlen(buf));
! 145: return 1;
! 146: } else { /* just print what it points to */
! 147: ckfputs("symbolic link to ", stdout);
! 148: ckfputs(buf, stdout);
! 149: }
! 150: }
! 151: return 1;
! 152: #endif
! 153: #ifdef S_IFSOCK
! 154: #ifndef __COHERENT__
! 155: case S_IFSOCK:
! 156: ckfputs("socket", stdout);
! 157: return 1;
! 158: #endif
! 159: #endif
! 160: case S_IFREG:
! 161: break;
! 162: default:
! 163: error("invalid mode 0%o.\n", sb->st_mode);
! 164: /*NOTREACHED*/
! 165: }
! 166:
! 167: /*
! 168: * regular file, check next possibility
! 169: */
! 170: if (sb->st_size == 0) {
! 171: ckfputs("empty", stdout);
! 172: return 1;
! 173: }
! 174: return 0;
! 175: }
! 176: