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