Commit | Line | Data |
---|---|---|
15637ed4 RG |
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> | |
286a6f32 | 29 | #include <string.h> |
15637ed4 | 30 | #include <sys/types.h> |
286a6f32 C |
31 | #include <sys/stat.h> |
32 | #include <unistd.h> | |
33 | #include <stdlib.h> | |
15637ed4 RG |
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 | |
286a6f32 | 42 | to point at the file that defines the "major" macro. |
15637ed4 | 43 | #endif /*major*/ |
286a6f32 | 44 | |
15637ed4 RG |
45 | #include "file.h" |
46 | ||
47 | #ifndef lint | |
48 | static char *moduleid = | |
286a6f32 | 49 | "@(#)fsmagic.c,v 1.3 1993/06/10 00:38:10 jtc Exp"; |
15637ed4 RG |
50 | #endif /* lint */ |
51 | ||
286a6f32 C |
52 | int |
53 | fsmagic(fn, sb) | |
54 | const char *fn; | |
55 | struct stat *sb; | |
15637ed4 | 56 | { |
286a6f32 | 57 | int ret = 0; |
15637ed4 RG |
58 | |
59 | /* | |
60 | * Fstat is cheaper but fails for files you don't have read perms on. | |
286a6f32 | 61 | * On 4.2BSD and similar systems, use lstat() to identify symlinks. |
15637ed4 RG |
62 | */ |
63 | #ifdef S_IFLNK | |
286a6f32 C |
64 | if (!lflag) |
65 | ret = lstat(fn, sb); | |
66 | else | |
15637ed4 | 67 | #endif |
286a6f32 | 68 | ret = stat(fn, sb); /* don't merge into if; see "ret =" above */ |
15637ed4 | 69 | |
286a6f32 C |
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); | |
15637ed4 | 81 | |
286a6f32 | 82 | switch (sb->st_mode & S_IFMT) { |
15637ed4 RG |
83 | case S_IFDIR: |
84 | ckfputs("directory", stdout); | |
85 | return 1; | |
86 | case S_IFCHR: | |
87 | (void) printf("character special (%d/%d)", | |
286a6f32 | 88 | major(sb->st_rdev), minor(sb->st_rdev)); |
15637ed4 RG |
89 | return 1; |
90 | case S_IFBLK: | |
91 | (void) printf("block special (%d/%d)", | |
286a6f32 | 92 | major(sb->st_rdev), minor(sb->st_rdev)); |
15637ed4 RG |
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: | |
286a6f32 C |
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 | } | |
15637ed4 RG |
151 | return 1; |
152 | #endif | |
153 | #ifdef S_IFSOCK | |
154 | case S_IFSOCK: | |
155 | ckfputs("socket", stdout); | |
156 | return 1; | |
157 | #endif | |
158 | case S_IFREG: | |
159 | break; | |
160 | default: | |
286a6f32 C |
161 | error("invalid mode 0%o.\n", sb->st_mode); |
162 | /*NOTREACHED*/ | |
15637ed4 RG |
163 | } |
164 | ||
165 | /* | |
166 | * regular file, check next possibility | |
167 | */ | |
286a6f32 | 168 | if (sb->st_size == 0) { |
15637ed4 RG |
169 | ckfputs("empty", stdout); |
170 | return 1; | |
171 | } | |
172 | return 0; | |
173 | } | |
174 |