Annotation of src/usr.bin/file/fsmagic.c, Revision 1.7
1.7 ! ian 1: /* $OpenBSD: fsmagic.c,v 1.6 2001/11/19 19:02:13 mpech Exp $ */
1.3 millert 2:
1.1 deraadt 3: /*
4: * fsmagic - magic based on filesystem info - directory, special files, etc.
5: *
1.7 ! ian 6: * Copyright (c) Ian F. Darwin 1986-1995.
! 7: * Software written by Ian F. Darwin and others;
! 8: * maintained 1995-present by Christos Zoulas and others.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice immediately at the beginning of the file, without modification,
! 15: * this list of conditions, and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by Ian F. Darwin and others.
! 22: * 4. The name of the author may not be used to endorse or promote products
! 23: * derived from this software without specific prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
! 29: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 35: * SUCH DAMAGE.
1.1 deraadt 36: */
37:
38: #include <stdio.h>
39: #include <string.h>
40: #include <sys/types.h>
41: #include <sys/stat.h>
42: #include <unistd.h>
43: #include <stdlib.h>
1.4 mickey 44: #include <err.h>
1.3 millert 45: #ifndef major
46: # if defined(__SVR4) || defined(_SVR4_SOURCE)
47: # include <sys/mkdev.h>
48: # endif
49: #endif
1.1 deraadt 50: #ifndef major /* if `major' not defined in types.h, */
51: #include <sys/sysmacros.h> /* try this one. */
52: #endif
53: #ifndef major /* still not defined? give up, manual intervention needed */
54: /* If cc tries to compile this, read and act on it. */
55: /* On most systems cpp will discard it automatically */
56: Congratulations, you have found a portability bug.
57: Please grep /usr/include/sys and edit the above #include
58: to point at the file that defines the "major" macro.
59: #endif /*major*/
60:
61: #include "file.h"
62:
63: #ifndef lint
1.7 ! ian 64: static char *moduleid = "$OpenBSD: fsmagic.c,v 1.6 2001/11/19 19:02:13 mpech Exp $";
1.1 deraadt 65: #endif /* lint */
66:
67: int
68: fsmagic(fn, sb)
69: const char *fn;
70: struct stat *sb;
71: {
72: int ret = 0;
73:
74: /*
75: * Fstat is cheaper but fails for files you don't have read perms on.
76: * On 4.2BSD and similar systems, use lstat() to identify symlinks.
77: */
78: #ifdef S_IFLNK
79: if (!lflag)
80: ret = lstat(fn, sb);
81: else
82: #endif
83: ret = stat(fn, sb); /* don't merge into if; see "ret =" above */
84:
85: if (ret) {
86: ckfprintf(stdout,
87: /* Yes, I do mean stdout. */
88: /* No \n, caller will provide. */
89: "can't stat `%s' (%s).", fn, strerror(errno));
90: return 1;
91: }
92:
93: if (sb->st_mode & S_ISUID) ckfputs("setuid ", stdout);
94: if (sb->st_mode & S_ISGID) ckfputs("setgid ", stdout);
95: if (sb->st_mode & S_ISVTX) ckfputs("sticky ", stdout);
96:
97: switch (sb->st_mode & S_IFMT) {
98: case S_IFDIR:
99: ckfputs("directory", stdout);
100: return 1;
101: case S_IFCHR:
1.3 millert 102: (void) printf("character special (%ld/%ld)",
103: (long) major(sb->st_rdev), (long) minor(sb->st_rdev));
1.1 deraadt 104: return 1;
105: case S_IFBLK:
1.3 millert 106: (void) printf("block special (%ld/%ld)",
107: (long) major(sb->st_rdev), (long) minor(sb->st_rdev));
1.1 deraadt 108: return 1;
109: /* TODO add code to handle V7 MUX and Blit MUX files */
110: #ifdef S_IFIFO
111: case S_IFIFO:
112: ckfputs("fifo (named pipe)", stdout);
113: return 1;
114: #endif
115: #ifdef S_IFLNK
116: case S_IFLNK:
117: {
118: char buf[BUFSIZ+4];
1.6 mpech 119: int nch;
1.1 deraadt 120: struct stat tstatbuf;
121:
122: if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
123: ckfprintf(stdout, "unreadable symlink (%s).",
124: strerror(errno));
125: return 1;
126: }
127: buf[nch] = '\0'; /* readlink(2) forgets this */
128:
129: /* If broken symlink, say so and quit early. */
130: if (*buf == '/') {
131: if (stat(buf, &tstatbuf) < 0) {
132: ckfprintf(stdout,
133: "broken symbolic link to %s", buf);
134: return 1;
135: }
136: }
137: else {
138: char *tmp;
139: char buf2[BUFSIZ+BUFSIZ+4];
140:
141: if ((tmp = strrchr(fn, '/')) == NULL) {
142: tmp = buf; /* in current directory anyway */
1.5 deraadt 143: } else if (strlen(fn) + strlen(buf) > sizeof(buf2)-1) {
144: ckfprintf(stdout, "name too long %s", fn);
145: return 1;
146: } else {
147: strcpy (buf2, fn); /* ok; take directory part */
1.1 deraadt 148: buf2[tmp-fn+1] = '\0';
1.5 deraadt 149: strcat (buf2, buf); /* ok; plus (relative) symlink */
1.1 deraadt 150: tmp = buf2;
151: }
152: if (stat(tmp, &tstatbuf) < 0) {
153: ckfprintf(stdout,
154: "broken symbolic link to %s", buf);
155: return 1;
156: }
157: }
158:
159: /* Otherwise, handle it. */
160: if (lflag) {
161: process(buf, strlen(buf));
162: return 1;
163: } else { /* just print what it points to */
164: ckfputs("symbolic link to ", stdout);
165: ckfputs(buf, stdout);
166: }
167: }
168: return 1;
169: #endif
170: #ifdef S_IFSOCK
171: #ifndef __COHERENT__
172: case S_IFSOCK:
173: ckfputs("socket", stdout);
174: return 1;
175: #endif
176: #endif
177: case S_IFREG:
178: break;
179: default:
1.4 mickey 180: errx(1, "invalid mode 0%o", sb->st_mode);
1.1 deraadt 181: /*NOTREACHED*/
182: }
183:
184: /*
185: * regular file, check next possibility
186: */
187: if (sb->st_size == 0) {
188: ckfputs("empty", stdout);
189: return 1;
190: }
191: return 0;
192: }
193: