287 lines
6.8 KiB
C
287 lines
6.8 KiB
C
|
/* @(#)file.c 1.10 09/08/04 joerg */
|
||
|
#include <schily/mconfig.h>
|
||
|
#ifndef lint
|
||
|
static UConst char sccsid[] =
|
||
|
"@(#)file.c 1.10 09/08/04 joerg";
|
||
|
#endif
|
||
|
/*
|
||
|
** find file types by using a modified "magic" file
|
||
|
**
|
||
|
** based on file v3.22 by Ian F. Darwin (see below)
|
||
|
**
|
||
|
** For each entry in the magic file, the message MUST start with
|
||
|
** two 4 character strings which are the CREATOR and TYPE for the
|
||
|
** Mac file. Any continuation lines are ignored. e.g magic entry
|
||
|
** for a GIF file:
|
||
|
**
|
||
|
** 0 string GIF8 8BIM GIFf
|
||
|
** >4 string 7a \b, version 8%s,
|
||
|
** >4 string 9a \b, version 8%s,
|
||
|
** >6 leshort >0 %hd x
|
||
|
** >8 leshort >0 %hd,
|
||
|
** #>10 byte &0x80 color mapped,
|
||
|
** #>10 byte&0x07 =0x00 2 colors
|
||
|
** #>10 byte&0x07 =0x01 4 colors
|
||
|
** #>10 byte&0x07 =0x02 8 colors
|
||
|
** #>10 byte&0x07 =0x03 16 colors
|
||
|
** #>10 byte&0x07 =0x04 32 colors
|
||
|
** #>10 byte&0x07 =0x05 64 colors
|
||
|
** #>10 byte&0x07 =0x06 128 colors
|
||
|
** #>10 byte&0x07 =0x07 256 colors
|
||
|
**
|
||
|
** Just the "8BIM" "GIFf" will be used whatever the type GIF file
|
||
|
** it is.
|
||
|
**
|
||
|
** Modified for mkhybrid James Pearson 19/5/98
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* file - find type of a file or files - main program.
|
||
|
*
|
||
|
* Copyright (c) Ian F. Darwin, 1987.
|
||
|
* Written by Ian F. Darwin.
|
||
|
*
|
||
|
* This software is not subject to any export provision of the United States
|
||
|
* Department of Commerce, and may be exported to any country or planet.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice immediately at the beginning of the file, without modification,
|
||
|
* this list of conditions, and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*/
|
||
|
#ifndef lint
|
||
|
static UConst char moduleid[] =
|
||
|
"@(#)$Id: file.c,v 1.38 1997/01/15 19:28:35 christos Exp $";
|
||
|
#endif /* lint */
|
||
|
|
||
|
#include <schily/stdio.h>
|
||
|
#include <schily/stdlib.h>
|
||
|
#include <schily/unistd.h> /* for read() */
|
||
|
#include <schily/stat.h>
|
||
|
#include <schily/fcntl.h> /* for open() */
|
||
|
|
||
|
#ifdef RESTORE_TIME
|
||
|
#include <schily/utime.h>
|
||
|
#ifdef HAVE_UTIMES
|
||
|
#define USE_UTIMES
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#if 0
|
||
|
#include <schily/in.h> /* for byte swapping */
|
||
|
#endif
|
||
|
|
||
|
#include "patchlevel.h"
|
||
|
#include "file.h"
|
||
|
|
||
|
#ifdef MAIN
|
||
|
/* Global command-line options */
|
||
|
#ifdef DEBUG
|
||
|
int debug = 1; /* debugging */
|
||
|
#else
|
||
|
int debug = 0; /* debugging */
|
||
|
#endif /* DEBUG */
|
||
|
int lflag = 0; /* follow Symlinks (BSD only) */
|
||
|
int zflag = 0; /* follow (uncompress) compressed files */
|
||
|
|
||
|
/* Misc globals */
|
||
|
char *magicfile; /* where magic be found */
|
||
|
|
||
|
char *progname; /* used throughout */
|
||
|
#endif
|
||
|
|
||
|
char * get_magic_match __PR((const char *inname));
|
||
|
void clean_magic __PR((void));
|
||
|
|
||
|
#if 0
|
||
|
static int byteconv4 __P((int, int, int));
|
||
|
static short byteconv2 __P((int, int, int));
|
||
|
#endif
|
||
|
|
||
|
#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
|
||
|
|
||
|
/*
|
||
|
* get_magic_match - get the CREATOR/TYPE string
|
||
|
* based on the original process()
|
||
|
*/
|
||
|
char *
|
||
|
get_magic_match(inname)
|
||
|
const char *inname;
|
||
|
{
|
||
|
int fd = 0;
|
||
|
unsigned char buf[HOWMANY+1]; /* one extra for terminating '\0' */
|
||
|
struct stat sb;
|
||
|
int nbytes = 0; /* number of bytes read from a datafile */
|
||
|
char *match;
|
||
|
|
||
|
/* check the file is regular and non-zero length */
|
||
|
if (stat(inname, &sb) != 0)
|
||
|
return 0;
|
||
|
|
||
|
if (sb.st_size == 0 || ! S_ISREG(sb.st_mode))
|
||
|
return 0;
|
||
|
|
||
|
if ((fd = open(inname, O_RDONLY)) < 0)
|
||
|
return 0;
|
||
|
|
||
|
/*
|
||
|
* try looking at the first HOWMANY bytes
|
||
|
*/
|
||
|
if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1)
|
||
|
return 0;
|
||
|
|
||
|
if (nbytes == 0)
|
||
|
return 0;
|
||
|
else {
|
||
|
buf[nbytes++] = '\0'; /* null-terminate it */
|
||
|
match = softmagic(buf, nbytes);
|
||
|
}
|
||
|
|
||
|
#ifdef RESTORE_TIME
|
||
|
/* really no point as we going to access the file later anyway */
|
||
|
{
|
||
|
/*
|
||
|
* Try to restore access, modification times if read it.
|
||
|
*/
|
||
|
# ifdef USE_UTIMES
|
||
|
struct timeval utsbuf[2];
|
||
|
utsbuf[0].tv_sec = sb.st_atime;
|
||
|
utsbuf[1].tv_sec = sb.st_mtime;
|
||
|
|
||
|
(void) utimes(inname, utsbuf); /* don't care if loses */
|
||
|
# else
|
||
|
struct utimbuf utbuf;
|
||
|
|
||
|
utbuf.actime = sb.st_atime;
|
||
|
utbuf.modtime = sb.st_mtime;
|
||
|
(void) utime(inname, &utbuf); /* don't care if loses */
|
||
|
# endif
|
||
|
}
|
||
|
#endif
|
||
|
(void) close(fd);
|
||
|
|
||
|
return(match);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* clean_magic - deallocate memory used
|
||
|
*/
|
||
|
void
|
||
|
clean_magic()
|
||
|
{
|
||
|
if (__f_magic)
|
||
|
free(__f_magic);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef MAIN
|
||
|
main(argc, argv)
|
||
|
int argc;
|
||
|
char **argv;
|
||
|
{
|
||
|
char *ret;
|
||
|
char creator[5];
|
||
|
char type[5];
|
||
|
|
||
|
if (argc < 3)
|
||
|
exit(1);
|
||
|
|
||
|
init_magic(argv[1]);
|
||
|
|
||
|
ret = get_magic_match(argv[2]);
|
||
|
|
||
|
if (!ret)
|
||
|
ret = "unixTEXT";
|
||
|
|
||
|
sscanf(ret, "%4s%4s", creator, type);
|
||
|
|
||
|
creator[4] = type[4] = '\0';
|
||
|
|
||
|
printf("%s %s\n", creator, type);
|
||
|
|
||
|
|
||
|
exit(0);
|
||
|
}
|
||
|
#endif /* MAIN */
|
||
|
|