cdrtools/libfile/file.c
2025-06-15 04:19:58 +08:00

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 */