version 1.4, 1997/01/15 23:42:26 |
version 1.5, 1997/02/09 23:58:22 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
|
|
/* |
/* |
* file - find type of a file or files - main program. |
* file - find type of a file or files - main program. |
* |
* |
|
|
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <fcntl.h> /* for open() */ |
#include <fcntl.h> /* for open() */ |
#if (__COHERENT__ >= 0x420) |
#if (__COHERENT__ >= 0x420) |
#include <sys/utime.h> |
# include <sys/utime.h> |
#else |
#else |
#include <utime.h> |
# ifdef USE_UTIMES |
|
# include <sys/time.h> |
|
# else |
|
# include <utime.h> |
|
# endif |
#endif |
#endif |
#include <unistd.h> /* for read() */ |
#include <unistd.h> /* for read() */ |
|
|
#ifdef __ELF__ |
#include <netinet/in.h> /* for byte swapping */ |
#include <elf.h> |
|
#endif |
|
|
|
#include "patchlevel.h" |
#include "patchlevel.h" |
#include "file.h" |
#include "file.h" |
|
|
int lineno; /* line number in the magic file */ |
int lineno; /* line number in the magic file */ |
|
|
|
|
static void unwrap __P((char *fn)); |
static void unwrap __P((char *fn)); |
|
#if 0 |
|
static int byteconv4 __P((int, int, int)); |
|
static short byteconv2 __P((int, int, int)); |
|
#endif |
|
|
/* |
/* |
* main - parse arguments and handle options |
* main - parse arguments and handle options |
|
|
FILE *f; |
FILE *f; |
int wid = 0, cwid; |
int wid = 0, cwid; |
|
|
if ((f = fopen(fn, "r")) == NULL) { |
if (strcmp("-", fn) == 0) { |
error("Cannot open `%s' (%s).\n", fn, strerror(errno)); |
f = stdin; |
/*NOTREACHED*/ |
wid = 1; |
} |
} else { |
|
if ((f = fopen(fn, "r")) == NULL) { |
|
error("Cannot open `%s' (%s).\n", fn, strerror(errno)); |
|
/*NOTREACHED*/ |
|
} |
|
|
while (fgets(buf, MAXPATHLEN, f) != NULL) { |
while (fgets(buf, sizeof(buf), f) != NULL) { |
cwid = strlen(buf) - 1; |
cwid = strlen(buf) - 1; |
if (cwid > wid) |
if (cwid > wid) |
wid = cwid; |
wid = cwid; |
|
} |
|
|
|
rewind(f); |
} |
} |
|
|
rewind(f); |
while (fgets(buf, sizeof(buf), f) != NULL) { |
|
|
while (fgets(buf, MAXPATHLEN, f) != NULL) { |
|
buf[strlen(buf)-1] = '\0'; |
buf[strlen(buf)-1] = '\0'; |
process(buf, wid); |
process(buf, wid); |
} |
} |
|
|
} |
} |
|
|
|
|
|
#if 0 |
/* |
/* |
|
* byteconv4 |
|
* Input: |
|
* from 4 byte quantity to convert |
|
* same whether to perform byte swapping |
|
* big_endian whether we are a big endian host |
|
*/ |
|
static int |
|
byteconv4(from, same, big_endian) |
|
int from; |
|
int same; |
|
int big_endian; |
|
{ |
|
if (same) |
|
return from; |
|
else if (big_endian) /* lsb -> msb conversion on msb */ |
|
{ |
|
union { |
|
int i; |
|
char c[4]; |
|
} retval, tmpval; |
|
|
|
tmpval.i = from; |
|
retval.c[0] = tmpval.c[3]; |
|
retval.c[1] = tmpval.c[2]; |
|
retval.c[2] = tmpval.c[1]; |
|
retval.c[3] = tmpval.c[0]; |
|
|
|
return retval.i; |
|
} |
|
else |
|
return ntohl(from); /* msb -> lsb conversion on lsb */ |
|
} |
|
|
|
/* |
|
* byteconv2 |
|
* Same as byteconv4, but for shorts |
|
*/ |
|
static short |
|
byteconv2(from, same, big_endian) |
|
int from; |
|
int same; |
|
int big_endian; |
|
{ |
|
if (same) |
|
return from; |
|
else if (big_endian) /* lsb -> msb conversion on msb */ |
|
{ |
|
union { |
|
short s; |
|
char c[2]; |
|
} retval, tmpval; |
|
|
|
tmpval.s = (short) from; |
|
retval.c[0] = tmpval.c[1]; |
|
retval.c[1] = tmpval.c[0]; |
|
|
|
return retval.s; |
|
} |
|
else |
|
return ntohs(from); /* msb -> lsb conversion on lsb */ |
|
} |
|
#endif |
|
|
|
/* |
* process - process input file |
* process - process input file |
*/ |
*/ |
void |
void |
|
|
int fd = 0; |
int fd = 0; |
static const char stdname[] = "standard input"; |
static const char stdname[] = "standard input"; |
unsigned char buf[HOWMANY+1]; /* one extra for terminating '\0' */ |
unsigned char buf[HOWMANY+1]; /* one extra for terminating '\0' */ |
struct utimbuf utbuf; |
|
struct stat sb; |
struct stat sb; |
int nbytes = 0; /* number of bytes read from a datafile */ |
int nbytes = 0; /* number of bytes read from a datafile */ |
char match = '\0'; |
char match = '\0'; |
|
|
buf[nbytes++] = '\0'; /* null-terminate it */ |
buf[nbytes++] = '\0'; /* null-terminate it */ |
match = tryit(buf, nbytes, zflag); |
match = tryit(buf, nbytes, zflag); |
} |
} |
#ifdef __ELF__ |
|
/* |
|
* ELF executables have multiple section headers in arbitrary |
|
* file locations and thus file(1) cannot determine it from easily. |
|
* Instead we traverse thru all section headers until a symbol table |
|
* one is found or else the binary is stripped. |
|
* XXX: This will not work for binaries of a different byteorder. |
|
* Should come up with a better fix. |
|
*/ |
|
|
|
if (match == 's' && nbytes > sizeof (Elf32_Ehdr) && |
#ifdef BUILTIN_ELF |
buf[EI_MAG0] == ELFMAG0 && |
if (match == 's' && nbytes > 5) |
buf[EI_MAG1] == ELFMAG1 && |
tryelf(fd, buf, nbytes); |
buf[EI_MAG2] == ELFMAG2 && |
#endif |
buf[EI_MAG3] == ELFMAG3) { |
|
|
|
union { |
if (inname != stdname) { |
long l; |
#ifdef RESTORE_TIME |
char c[sizeof (long)]; |
|
} u; |
|
Elf32_Ehdr elfhdr; |
|
int stripped = 1; |
|
|
|
u.l = 1; |
|
(void) memcpy(&elfhdr, buf, sizeof elfhdr); |
|
|
|
/* |
/* |
* If the system byteorder does not equal the object byteorder |
* Try to restore access, modification times if read it. |
* then don't test. |
|
*/ |
*/ |
if ((u.c[sizeof(long) - 1] + 1) == elfhdr.e_ident[5]) { |
# ifdef USE_UTIMES |
if (lseek(fd, elfhdr.e_shoff, SEEK_SET)<0) |
struct timeval utsbuf[2]; |
error("lseek failed (%s).\n", strerror(errno)); |
utsbuf[0].tv_sec = sb.st_atime; |
|
utsbuf[1].tv_sec = sb.st_mtime; |
|
|
for ( ; elfhdr.e_shnum ; elfhdr.e_shnum--) { |
(void) utimes(inname, utsbuf); /* don't care if loses */ |
if (read(fd, buf, elfhdr.e_shentsize)<0) |
# else |
error("read failed (%s).\n", strerror(errno)); |
struct utimbuf utbuf; |
if (((Elf32_Shdr *)&buf)->sh_type == SHT_SYMTAB) { |
|
stripped = 0; |
|
break; |
|
} |
|
} |
|
if (stripped) |
|
(void) printf (", stripped"); |
|
} |
|
} |
|
#endif |
|
|
|
if (inname != stdname) |
utbuf.actime = sb.st_atime; |
|
utbuf.modtime = sb.st_mtime; |
|
(void) utime(inname, &utbuf); /* don't care if loses */ |
|
# endif |
|
#endif |
(void) close(fd); |
(void) close(fd); |
|
} |
(void) putchar('\n'); |
(void) putchar('\n'); |
} |
} |
|
|
|
|
/* try known keywords, check whether it is ASCII */ |
/* try known keywords, check whether it is ASCII */ |
if (ascmagic(buf, nb)) |
if (ascmagic(buf, nb)) |
return 'a'; |
return 'a'; |
|
|
|
/* see if it's international language text */ |
|
if (internatmagic(buf, nb)) |
|
return 'i'; |
|
|
/* abandon hope, all ye who remain here */ |
/* abandon hope, all ye who remain here */ |
ckfputs("data", stdout); |
ckfputs("data", stdout); |