Annotation of src/usr.bin/file/fsmagic.c, Revision 1.5
1.5 ! deraadt 1: /* $OpenBSD: fsmagic.c,v 1.4 1998/07/10 15:05:22 mickey Exp $ */
1.3 millert 2:
1.1 deraadt 3: /*
4: * fsmagic - magic based on filesystem info - directory, special files, etc.
5: *
6: * Copyright (c) Ian F. Darwin, 1987.
7: * Written by Ian F. Darwin.
8: *
9: * This software is not subject to any license of the American Telephone
10: * and Telegraph Company or of the Regents of the University of California.
11: *
12: * Permission is granted to anyone to use this software for any purpose on
13: * any computer system, and to alter it and redistribute it freely, subject
14: * to the following restrictions:
15: *
16: * 1. The author is not responsible for the consequences of use of this
17: * software, no matter how awful, even if they arise from flaws in it.
18: *
19: * 2. The origin of this software must not be misrepresented, either by
20: * explicit claim or by omission. Since few users ever read sources,
21: * credits must appear in the documentation.
22: *
23: * 3. Altered versions must be plainly marked as such, and must not be
24: * misrepresented as being the original software. Since few users
25: * ever read sources, credits must appear in the documentation.
26: *
27: * 4. This notice may not be removed or altered.
28: */
29:
30: #include <stdio.h>
31: #include <string.h>
32: #include <sys/types.h>
33: #include <sys/stat.h>
34: #include <unistd.h>
35: #include <stdlib.h>
1.4 mickey 36: #include <err.h>
1.3 millert 37: #ifndef major
38: # if defined(__SVR4) || defined(_SVR4_SOURCE)
39: # include <sys/mkdev.h>
40: # endif
41: #endif
1.1 deraadt 42: #ifndef major /* if `major' not defined in types.h, */
43: #include <sys/sysmacros.h> /* try this one. */
44: #endif
45: #ifndef major /* still not defined? give up, manual intervention needed */
46: /* If cc tries to compile this, read and act on it. */
47: /* On most systems cpp will discard it automatically */
48: Congratulations, you have found a portability bug.
49: Please grep /usr/include/sys and edit the above #include
50: to point at the file that defines the "major" macro.
51: #endif /*major*/
52:
53: #include "file.h"
54:
55: #ifndef lint
1.5 ! deraadt 56: static char *moduleid = "$OpenBSD: fsmagic.c,v 1.4 1998/07/10 15:05:22 mickey Exp $";
1.1 deraadt 57: #endif /* lint */
58:
59: int
60: fsmagic(fn, sb)
61: const char *fn;
62: struct stat *sb;
63: {
64: int ret = 0;
65:
66: /*
67: * Fstat is cheaper but fails for files you don't have read perms on.
68: * On 4.2BSD and similar systems, use lstat() to identify symlinks.
69: */
70: #ifdef S_IFLNK
71: if (!lflag)
72: ret = lstat(fn, sb);
73: else
74: #endif
75: ret = stat(fn, sb); /* don't merge into if; see "ret =" above */
76:
77: if (ret) {
78: ckfprintf(stdout,
79: /* Yes, I do mean stdout. */
80: /* No \n, caller will provide. */
81: "can't stat `%s' (%s).", fn, strerror(errno));
82: return 1;
83: }
84:
85: if (sb->st_mode & S_ISUID) ckfputs("setuid ", stdout);
86: if (sb->st_mode & S_ISGID) ckfputs("setgid ", stdout);
87: if (sb->st_mode & S_ISVTX) ckfputs("sticky ", stdout);
88:
89: switch (sb->st_mode & S_IFMT) {
90: case S_IFDIR:
91: ckfputs("directory", stdout);
92: return 1;
93: case S_IFCHR:
1.3 millert 94: (void) printf("character special (%ld/%ld)",
95: (long) major(sb->st_rdev), (long) minor(sb->st_rdev));
1.1 deraadt 96: return 1;
97: case S_IFBLK:
1.3 millert 98: (void) printf("block special (%ld/%ld)",
99: (long) major(sb->st_rdev), (long) minor(sb->st_rdev));
1.1 deraadt 100: return 1;
101: /* TODO add code to handle V7 MUX and Blit MUX files */
102: #ifdef S_IFIFO
103: case S_IFIFO:
104: ckfputs("fifo (named pipe)", stdout);
105: return 1;
106: #endif
107: #ifdef S_IFLNK
108: case S_IFLNK:
109: {
110: char buf[BUFSIZ+4];
111: register int nch;
112: struct stat tstatbuf;
113:
114: if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
115: ckfprintf(stdout, "unreadable symlink (%s).",
116: strerror(errno));
117: return 1;
118: }
119: buf[nch] = '\0'; /* readlink(2) forgets this */
120:
121: /* If broken symlink, say so and quit early. */
122: if (*buf == '/') {
123: if (stat(buf, &tstatbuf) < 0) {
124: ckfprintf(stdout,
125: "broken symbolic link to %s", buf);
126: return 1;
127: }
128: }
129: else {
130: char *tmp;
131: char buf2[BUFSIZ+BUFSIZ+4];
132:
133: if ((tmp = strrchr(fn, '/')) == NULL) {
134: tmp = buf; /* in current directory anyway */
1.5 ! deraadt 135: } else if (strlen(fn) + strlen(buf) > sizeof(buf2)-1) {
! 136: ckfprintf(stdout, "name too long %s", fn);
! 137: return 1;
! 138: } else {
! 139: strcpy (buf2, fn); /* ok; take directory part */
1.1 deraadt 140: buf2[tmp-fn+1] = '\0';
1.5 ! deraadt 141: strcat (buf2, buf); /* ok; plus (relative) symlink */
1.1 deraadt 142: tmp = buf2;
143: }
144: if (stat(tmp, &tstatbuf) < 0) {
145: ckfprintf(stdout,
146: "broken symbolic link to %s", buf);
147: return 1;
148: }
149: }
150:
151: /* Otherwise, handle it. */
152: if (lflag) {
153: process(buf, strlen(buf));
154: return 1;
155: } else { /* just print what it points to */
156: ckfputs("symbolic link to ", stdout);
157: ckfputs(buf, stdout);
158: }
159: }
160: return 1;
161: #endif
162: #ifdef S_IFSOCK
163: #ifndef __COHERENT__
164: case S_IFSOCK:
165: ckfputs("socket", stdout);
166: return 1;
167: #endif
168: #endif
169: case S_IFREG:
170: break;
171: default:
1.4 mickey 172: errx(1, "invalid mode 0%o", sb->st_mode);
1.1 deraadt 173: /*NOTREACHED*/
174: }
175:
176: /*
177: * regular file, check next possibility
178: */
179: if (sb->st_size == 0) {
180: ckfputs("empty", stdout);
181: return 1;
182: }
183: return 0;
184: }
185: