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 #include "system.h"
00029 #include "file.h"
00030 #include "debug.h"
00031
00032 FILE_RCSID("@(#)Id: fsmagic.c,v 1.36 2002/07/03 19:00:41 christos Exp ")
00033
00034
00035
00036
00037 int
00038 fmagicD(fmagic fm)
00039 {
00040 const char * fn = fm->fn;
00041 struct stat * st = &fm->sb;
00042 int ret = 0;
00043 int xx;
00044
00045
00046
00047
00048
00049 #if defined(S_IFLNK) || defined(__LCLINT__)
00050 if (!(fm->flags & FMAGIC_FLAGS_FOLLOW))
00051 ret = lstat(fn, st);
00052 else
00053 #endif
00054 ret = stat(fn, st);
00055
00056 if (ret) {
00057
00058
00059 fmagicPrintf(fm, "can't stat `%s' (%s).", fn, strerror(errno));
00060 return 1;
00061 }
00062
00063 if ((fm->flags & FMAGIC_FLAGS_MIME)) {
00064 if ((st->st_mode & S_IFMT) != S_IFREG) {
00065 fmagicPrintf(fm, "application/x-not-regular-file");
00066 return 1;
00067 }
00068 }
00069 else {
00070 #if defined(S_ISUID) || defined(__LCLINT__)
00071 if (st->st_mode & S_ISUID) fmagicPrintf(fm, "setuid ");
00072 #endif
00073 #if defined(S_ISGID) || defined(__LCLINT__)
00074 if (st->st_mode & S_ISGID) fmagicPrintf(fm, "setgid ");
00075 #endif
00076 #if defined(S_ISVTX) || defined(__LCLINT__)
00077 if (st->st_mode & S_ISVTX) fmagicPrintf(fm, "sticky ");
00078 #endif
00079 }
00080
00081 switch (st->st_mode & S_IFMT) {
00082 case S_IFDIR:
00083 fmagicPrintf(fm, "directory");
00084 return 1;
00085 #if defined(S_IFCHR) || defined(__LCLINT__)
00086 case S_IFCHR:
00087
00088
00089
00090
00091
00092 if ((fm->flags & FMAGIC_FLAGS_SPECIAL))
00093 break;
00094 #ifdef HAVE_STRUCT_STAT_ST_RDEV
00095 # ifdef dv_unit
00096 fmagicPrintf(fm, "character special (%d/%d/%d)",
00097 major(st->st_rdev),
00098 dv_unit(st->st_rdev),
00099 dv_subunit(st->st_rdev));
00100 # else
00101
00102 fmagicPrintf(fm, "character special (%ld/%ld)",
00103 (long) major(st->st_rdev), (long) minor(st->st_rdev));
00104
00105 # endif
00106 #else
00107 fmagicPrintf(fm, "character special");
00108 #endif
00109 return 1;
00110 #endif
00111 #if defined(S_IFBLK) || defined(__LCLINT__)
00112 case S_IFBLK:
00113
00114
00115
00116
00117
00118 if ((fm->flags & FMAGIC_FLAGS_SPECIAL))
00119 break;
00120 #ifdef HAVE_STRUCT_STAT_ST_RDEV
00121 # ifdef dv_unit
00122 fmagicPrintf(fm, "block special (%d/%d/%d)",
00123 major(st->st_rdev),
00124 dv_unit(st->st_rdev),
00125 dv_subunit(st->st_rdev));
00126 # else
00127
00128 fmagicPrintf(fm, "block special (%ld/%ld)",
00129 (long) major(st->st_rdev), (long) minor(st->st_rdev));
00130
00131 # endif
00132 #else
00133 fmagicPrintf(fm, "block special");
00134 #endif
00135 return 1;
00136 #endif
00137
00138 #if defined(S_IFIFO) || defined(__LCLINT__)
00139 case S_IFIFO:
00140 fmagicPrintf(fm, "fifo (named pipe)");
00141 return 1;
00142 #endif
00143 #if defined(S_IFDOOR)
00144 case S_IFDOOR:
00145 fmagicPrintf(fm, "door");
00146 return 1;
00147 #endif
00148 #if defined(S_IFLNK) || defined(__LCLINT__)
00149 case S_IFLNK:
00150 {
00151 char buf[BUFSIZ+4];
00152 int nch;
00153 struct stat tstatbuf;
00154
00155 buf[0] = '\0';
00156 if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
00157 fmagicPrintf(fm, "unreadable symlink (%s).", strerror(errno));
00158 return 1;
00159 }
00160 buf[nch] = '\0';
00161
00162
00163
00164 if (*buf == '/') {
00165 if (stat(buf, &tstatbuf) < 0) {
00166 fmagicPrintf(fm, "broken symbolic link to %s", buf);
00167 return 1;
00168 }
00169 }
00170 else {
00171 char *tmp;
00172 char buf2[BUFSIZ+BUFSIZ+4];
00173
00174 if ((tmp = strrchr(fn, '/')) == NULL) {
00175 tmp = buf;
00176 }
00177 else {
00178 strcpy (buf2, fn);
00179 buf2[tmp-fn+1] = '\0';
00180 strcat (buf2, buf);
00181 tmp = buf2;
00182 }
00183 if (stat(tmp, &tstatbuf) < 0) {
00184 fmagicPrintf(fm, "broken symbolic link to %s", buf);
00185 return 1;
00186 }
00187 }
00188
00189
00190
00191 if ((fm->flags & FMAGIC_FLAGS_FOLLOW)) {
00192 fmagicPrintf(fm, "\n");
00193 xx = fmagicProcess(fm, buf, strlen(buf));
00194 return 1;
00195 } else {
00196 fmagicPrintf(fm, "symbolic link to %s", buf);
00197 }
00198 }
00199 return 1;
00200 #endif
00201 #if defined(S_IFSOCK)
00202 #ifndef __COHERENT__
00203 case S_IFSOCK:
00204 fmagicPrintf(fm, "socket");
00205 return 1;
00206 #endif
00207 #endif
00208 case S_IFREG:
00209 break;
00210 default:
00211 error(EXIT_FAILURE, 0, "invalid mode 0%o.\n", st->st_mode);
00212
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 if (!(fm->flags & FMAGIC_FLAGS_SPECIAL) && st->st_size == 0) {
00228 fmagicPrintf(fm, ((fm->flags & FMAGIC_FLAGS_MIME)
00229 ? "application/x-empty" : "empty"));
00230 return 1;
00231 }
00232 return 0;
00233 }
00234
00235
00236 int
00237 fmagicF(fmagic fm, int zfl)
00238 {
00239
00240
00241
00242
00243
00244 #ifdef __EMX__
00245
00246
00247
00248
00249 if (os2_apptype(fn, buf, nb) == 1)
00250 return 'o';
00251 #endif
00252
00253 if (zfl && fmagicZ(fm))
00254 return 'z';
00255
00256
00257 if (fmagicS(fm))
00258 return 's';
00259
00260
00261 if (fmagicA(fm))
00262 return 'a';
00263
00264
00265 fmagicPrintf(fm, ((fm->flags & FMAGIC_FLAGS_MIME)
00266 ? "application/octet-stream" : "data"));
00267 return '\0';
00268 }
00269
00270
00271
00272
00273
00274 int
00275 fmagicProcess(fmagic fm, const char *fn, int wid)
00276 {
00277 static const char stdname[] = "standard input";
00278 char match = '\0';
00279 int ret = 0;
00280
00281
00282 fm->fn = fn;
00283
00284 fm->buf = xmalloc(HOWMANY+1);
00285 fm->buf[0] = '\0';
00286 fm->nb = 0;
00287
00288
00289 if (strcmp("-", fn) == 0) {
00290 if (fstat(0, &fm->sb)<0) {
00291 error(EXIT_FAILURE, 0, "cannot fstat `%s' (%s).\n", stdname,
00292 strerror(errno));
00293
00294 }
00295 fm->fn = stdname;
00296 }
00297
00298
00299 if (wid > 0 && !(fm->flags & FMAGIC_FLAGS_BRIEF))
00300 fmagicPrintf(fm, "%s:%*s ", fm->fn,
00301 (int) (wid - strlen(fm->fn)), "");
00302
00303 if (fm->fn != stdname) {
00304
00305
00306
00307 if (fmagicD(fm) != 0)
00308 goto exit;
00309
00310 if ((fm->fd = open(fm->fn, O_RDONLY)) < 0) {
00311
00312 if (fm->sb.st_mode & 0002)
00313 fmagicPrintf(fm, "writeable, ");
00314 if (fm->sb.st_mode & 0111)
00315 fmagicPrintf(fm, "executable, ");
00316 fmagicPrintf(fm, "can't read `%s' (%s).", fm->fn, strerror(errno));
00317 goto exit;
00318 }
00319 }
00320
00321
00322
00323
00324
00325 if ((fm->nb = read(fm->fd, (char *)fm->buf, HOWMANY)) == -1) {
00326 error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
00327
00328 }
00329
00330 if (fm->nb == 0)
00331 fmagicPrintf(fm, ((fm->flags & FMAGIC_FLAGS_MIME)
00332 ? "application/x-empty" : "empty"), fm);
00333 else {
00334 fm->buf[fm->nb++] = '\0';
00335 match = fmagicF(fm, (fm->flags & FMAGIC_FLAGS_UNCOMPRESS));
00336 }
00337
00338 #ifdef BUILTIN_ELF
00339 if (match == 's' && fm->nb > 5) {
00340
00341
00342
00343
00344
00345
00346
00347
00348 fmagicE(fm);
00349 }
00350 #endif
00351
00352 if (fm->fn != stdname) {
00353 #ifdef RESTORE_TIME
00354
00355
00356
00357
00358
00359
00360 # ifdef USE_UTIMES
00361 struct timeval utsbuf[2];
00362 utsbuf[0].tv_sec = fm->sb.st_atime;
00363 utsbuf[1].tv_sec = fm->sb.st_mtime;
00364
00365 (void) utimes(fm->fn, utsbuf);
00366 # else
00367 struct utimbuf utbuf;
00368
00369 utbuf.actime = fm->sb.st_atime;
00370 utbuf.modtime = fm->sb.st_mtime;
00371 (void) utime(fm->fn, &utbuf);
00372 # endif
00373 #endif
00374 (void) close(fm->fd);
00375 fm->fd = -1;
00376 }
00377
00378 exit:
00379 if (fm->buf != NULL)
00380 free(fm->buf);
00381 fm->buf = NULL;
00382 fm->nb = 0;
00383 return ret;
00384 }
00385