00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "file.h"
00033 #include "magic.h"
00034 #include <string.h>
00035 #ifdef HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038 #include <stdlib.h>
00039 #include <sys/stat.h>
00040
00041 #ifdef MAJOR_IN_MKDEV
00042 # include <sys/mkdev.h>
00043 # define HAVE_MAJOR
00044 #endif
00045 #ifdef MAJOR_IN_SYSMACROS
00046 # include <sys/sysmacros.h>
00047 # define HAVE_MAJOR
00048 #endif
00049 #ifdef major
00050 # define HAVE_MAJOR
00051 #endif
00052
00053 #ifndef HAVE_MAJOR
00054 # define major(dev) (((dev) >> 8) & 0xff)
00055 # define minor(dev) ((dev) & 0xff)
00056 #endif
00057 #undef HAVE_MAJOR
00058
00059 #ifndef lint
00060 FILE_RCSID("@(#)$Id: fsmagic.c,v 1.46 2005/06/25 15:52:14 christos Exp $")
00061 #endif
00062
00063 protected int
00064 file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
00065 {
00066 int ret = 0;
00067 #ifdef S_IFLNK
00068 char buf[BUFSIZ+4];
00069 int nch;
00070 struct stat tstatbuf;
00071 #endif
00072
00073 if (fn == NULL)
00074 return 0;
00075
00076
00077
00078
00079
00080 #ifdef S_IFLNK
00081 if ((ms->flags & MAGIC_SYMLINK) == 0)
00082 ret = lstat(fn, sb);
00083 else
00084 #endif
00085 ret = stat(fn, sb);
00086
00087 if (ret) {
00088 if (ms->flags & MAGIC_ERROR) {
00089 file_error(ms, errno, "cannot stat `%s'", fn);
00090 return -1;
00091 }
00092 if (file_printf(ms, "cannot open `%s' (%s)",
00093 fn, strerror(errno)) == -1)
00094 return -1;
00095 ms->haderr++;
00096 return -1;
00097 }
00098
00099 if ((ms->flags & MAGIC_MIME) != 0) {
00100 if ((sb->st_mode & S_IFMT) != S_IFREG) {
00101 if (file_printf(ms, "application/x-not-regular-file")
00102 == -1)
00103 return -1;
00104 return 1;
00105 }
00106 }
00107 else {
00108 #ifdef S_ISUID
00109 if (sb->st_mode & S_ISUID)
00110 if (file_printf(ms, "setuid ") == -1)
00111 return -1;
00112 #endif
00113 #ifdef S_ISGID
00114 if (sb->st_mode & S_ISGID)
00115 if (file_printf(ms, "setgid ") == -1)
00116 return -1;
00117 #endif
00118 #ifdef S_ISVTX
00119 if (sb->st_mode & S_ISVTX)
00120 if (file_printf(ms, "sticky ") == -1)
00121 return -1;
00122 #endif
00123 }
00124
00125 switch (sb->st_mode & S_IFMT) {
00126 case S_IFDIR:
00127 if (file_printf(ms, "directory") == -1)
00128 return -1;
00129 return 1;
00130 #ifdef S_IFCHR
00131 case S_IFCHR:
00132
00133
00134
00135
00136
00137 if ((ms->flags & MAGIC_DEVICES) != 0)
00138 break;
00139 #ifdef HAVE_ST_RDEV
00140 # ifdef dv_unit
00141 if (file_printf(ms, "character special (%d/%d/%d)",
00142 major(sb->st_rdev), dv_unit(sb->st_rdev),
00143 dv_subunit(sb->st_rdev)) == -1)
00144 return -1;
00145 # else
00146 if (file_printf(ms, "character special (%ld/%ld)",
00147 (long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1)
00148 return -1;
00149 # endif
00150 #else
00151 if (file_printf(ms, "character special") == -1)
00152 return -1;
00153 #endif
00154 return 1;
00155 #endif
00156 #ifdef S_IFBLK
00157 case S_IFBLK:
00158
00159
00160
00161
00162
00163 if ((ms->flags & MAGIC_DEVICES) != 0)
00164 break;
00165 #ifdef HAVE_ST_RDEV
00166 # ifdef dv_unit
00167 if (file_printf(ms, "block special (%d/%d/%d)",
00168 major(sb->st_rdev), dv_unit(sb->st_rdev),
00169 dv_subunit(sb->st_rdev)) == -1)
00170 return -1;
00171 # else
00172 if (file_printf(ms, "block special (%ld/%ld)",
00173 (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
00174 return -1;
00175 # endif
00176 #else
00177 if (file_printf(ms, "block special") == -1)
00178 return -1;
00179 #endif
00180 return 1;
00181 #endif
00182
00183 #ifdef S_IFIFO
00184 case S_IFIFO:
00185 if((ms->flags & MAGIC_DEVICES) != 0)
00186 break;
00187 if (file_printf(ms, "fifo (named pipe)") == -1)
00188 return -1;
00189 return 1;
00190 #endif
00191 #ifdef S_IFDOOR
00192 case S_IFDOOR:
00193 if (file_printf(ms, "door") == -1)
00194 return -1;
00195 return 1;
00196 #endif
00197 #ifdef S_IFLNK
00198 case S_IFLNK:
00199 if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
00200 if (ms->flags & MAGIC_ERROR) {
00201 file_error(ms, errno, "unreadable symlink `%s'",
00202 fn);
00203 return -1;
00204 }
00205 if (file_printf(ms,
00206 "unreadable symlink `%s' (%s)", fn,
00207 strerror(errno)) == -1)
00208 return -1;
00209 return 1;
00210 }
00211 buf[nch] = '\0';
00212
00213
00214 if (*buf == '/') {
00215 if (stat(buf, &tstatbuf) < 0) {
00216 if (ms->flags & MAGIC_ERROR) {
00217 file_error(ms, errno,
00218 "broken symbolic link to `%s'", buf);
00219 return -1;
00220 }
00221 if (file_printf(ms, "broken symbolic link to `%s'",
00222 buf) == -1)
00223 return -1;
00224 return 1;
00225 }
00226 }
00227 else {
00228 char *tmp;
00229 char buf2[BUFSIZ+BUFSIZ+4];
00230
00231 if ((tmp = strrchr(fn, '/')) == NULL) {
00232 tmp = buf;
00233 } else {
00234 if (tmp - fn + 1 > BUFSIZ) {
00235 if (ms->flags & MAGIC_ERROR) {
00236 file_error(ms, 0,
00237 "path too long: `%s'", buf);
00238 return -1;
00239 }
00240 if (file_printf(ms,
00241 "path too long: `%s'", fn) == -1)
00242 return -1;
00243 return 1;
00244 }
00245 (void)strcpy(buf2, fn);
00246 buf2[tmp - fn + 1] = '\0';
00247 (void)strcat(buf2, buf);
00248 tmp = buf2;
00249 }
00250 if (stat(tmp, &tstatbuf) < 0) {
00251 if (ms->flags & MAGIC_ERROR) {
00252 file_error(ms, errno,
00253 "broken symbolic link to `%s'",
00254 buf);
00255 return -1;
00256 }
00257 if (file_printf(ms,
00258 "broken symbolic link to `%s'", buf) == -1)
00259 return -1;
00260 return 1;
00261 }
00262 }
00263
00264
00265 if ((ms->flags & MAGIC_SYMLINK) != 0) {
00266 const char *p;
00267 ms->flags &= MAGIC_SYMLINK;
00268 p = magic_file(ms, buf);
00269 ms->flags |= MAGIC_SYMLINK;
00270 return p != NULL ? 1 : -1;
00271 } else {
00272 if (file_printf(ms, "symbolic link to `%s'",
00273 buf) == -1)
00274 return -1;
00275 }
00276 return 1;
00277 #endif
00278 #ifdef S_IFSOCK
00279 #ifndef __COHERENT__
00280 case S_IFSOCK:
00281 if (file_printf(ms, "socket") == -1)
00282 return -1;
00283 return 1;
00284 #endif
00285 #endif
00286 case S_IFREG:
00287 break;
00288 default:
00289 file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
00290 return -1;
00291 break;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
00307 if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
00308 "application/x-empty" : "empty") == -1)
00309 return -1;
00310 return 1;
00311 }
00312 return 0;
00313 }