24 changed files with 110003 additions and 0 deletions
-
33ext/fileinfo/config.m4
-
17ext/fileinfo/create_data_file.php
-
101727ext/fileinfo/data_file.c
-
454ext/fileinfo/fileinfo.c
-
170ext/fileinfo/libmagic/apptype.c
-
792ext/fileinfo/libmagic/ascmagic.c
-
492ext/fileinfo/libmagic/compress.c
-
5ext/fileinfo/libmagic/config.h
-
67ext/fileinfo/libmagic/elfclass.h
-
481ext/fileinfo/libmagic/file.c
-
392ext/fileinfo/libmagic/file.h
-
48ext/fileinfo/libmagic/file_opts.h
-
312ext/fileinfo/libmagic/fsmagic.c
-
482ext/fileinfo/libmagic/getopt_long.c
-
156ext/fileinfo/libmagic/is_tar.c
-
397ext/fileinfo/libmagic/magic.c
-
82ext/fileinfo/libmagic/magic.h
-
173ext/fileinfo/libmagic/names.h
-
337ext/fileinfo/libmagic/patchlevel.h
-
236ext/fileinfo/libmagic/print.c
-
1016ext/fileinfo/libmagic/readelf.c
-
236ext/fileinfo/libmagic/readelf.h
-
1825ext/fileinfo/libmagic/softmagic.c
-
73ext/fileinfo/libmagic/tar.h
@ -0,0 +1,33 @@ |
|||
dnl $Id$ |
|||
dnl config.m4 for extension fileinfo |
|||
|
|||
PHP_ARG_WITH(fileinfo, for fileinfo support, |
|||
[ --with-fileinfo=DIR Include fileinfo support]) |
|||
|
|||
if test "$PHP_FILEINFO" != "no"; then |
|||
MAGIC_MIME_DIRS="/usr/local/share/file /usr/share/file /usr/share/misc/file /etc /usr/share/misc" |
|||
MAGIC_MIME_FILENAMES="magic magic.mime" |
|||
|
|||
for i in $MAGIC_MIME_DIRS; do |
|||
for j in $MAGIC_MIME_FILENAMES; do |
|||
if test -f "$i/$j"; then |
|||
PHP_DEFAULT_MAGIC_FILE="$i/$j" |
|||
break |
|||
fi |
|||
done |
|||
done |
|||
|
|||
AC_DEFINE_UNQUOTED(PHP_DEFAULT_MAGIC_FILE,"$PHP_DEFAULT_MAGIC_FILE",[magic file path]) |
|||
|
|||
libmagic_sources=" \ |
|||
libmagic/apprentice.c libmagic/apptype.c libmagic/ascmagic.c \ |
|||
libmagic/compress.c libmagic/fsmagic.c libmagic/funcs.c \ |
|||
libmagic/getopt_long.c libmagic/is_tar.c libmagic/magic.c libmagic/print.c \ |
|||
libmagic/readelf.c libmagic/softmagic.c" |
|||
|
|||
PHP_NEW_EXTENSION(fileinfo, fileinfo.c $libmagic_sources, $ext_shared,,-I@ext_srcdir@/libmagic) |
|||
PHP_SUBST(FILEINFO_SHARED_LIBADD) |
|||
PHP_ADD_BUILD_DIR($ext_builddir/libmagic) |
|||
|
|||
AC_CHECK_FUNCS([utimes]) |
|||
fi |
|||
@ -0,0 +1,17 @@ |
|||
/* This is a generated file, do not modify */ |
|||
/* Usage: php create_data_file.php /path/to/magic.mgc > data_file.c */ |
|||
<?php |
|||
$dta = file_get_contents( $argv[1] ); |
|||
$dta_l = strlen($dta); |
|||
$j = 0; |
|||
|
|||
echo "const unsigned char php_magic_database[$dta_l] = {\n"; |
|||
for ($i = 0; $i < $dta_l; $i++) { |
|||
printf("0x%02X, ", ord($dta[$i])); |
|||
if ($j % 16 == 15) { |
|||
echo "\n"; |
|||
} |
|||
$j++; |
|||
} |
|||
echo "};\n"; |
|||
?>
|
|||
101727
ext/fileinfo/data_file.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,454 @@ |
|||
/* |
|||
+----------------------------------------------------------------------+ |
|||
| PHP Version 5 | |
|||
+----------------------------------------------------------------------+ |
|||
| Copyright (c) 1997-2004 The PHP Group | |
|||
+----------------------------------------------------------------------+ |
|||
| This source file is subject to version 3.0 of the PHP license, | |
|||
| that is bundled with this package in the file LICENSE, and is | |
|||
| available through the world-wide-web at the following url: | |
|||
| http://www.php.net/license/3_0.txt. | |
|||
| If you did not receive a copy of the PHP license and are unable to | |
|||
| obtain it through the world-wide-web, please send a note to | |
|||
| license@php.net so we can mail you a copy immediately. | |
|||
+----------------------------------------------------------------------+ |
|||
| Author: Ilia Alshanetsky <ilia@php.net> | |
|||
+----------------------------------------------------------------------+ |
|||
*/ |
|||
|
|||
/* $Id$ */ |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include "config.h" |
|||
#endif |
|||
#include "php.h" |
|||
|
|||
#include <magic.h> |
|||
/* |
|||
* HOWMANY specifies the maximum offset libmagic will look at |
|||
* this is currently hardcoded in the libmagic source but not exported |
|||
*/ |
|||
#ifndef HOWMANY |
|||
#define HOWMANY 65536 |
|||
#endif |
|||
|
|||
#include "php_ini.h" |
|||
#include "ext/standard/info.h" |
|||
#include "ext/standard/file.h" /* needed for context stuff */ |
|||
#include "php_fileinfo.h" |
|||
#include "fopen_wrappers.h" /* needed for is_url */ |
|||
|
|||
/* {{{ macros and type definitions */ |
|||
struct php_fileinfo { |
|||
long options; |
|||
struct magic_set *magic; |
|||
}; |
|||
|
|||
#ifndef PHP_DEFAULT_MAGIC_FILE |
|||
#define PHP_DEFAULT_MAGIC_FILE NULL |
|||
#endif |
|||
|
|||
#ifdef ZEND_ENGINE_2 |
|||
/* {{{ */ |
|||
static zend_object_handlers finfo_object_handlers; |
|||
zend_class_entry *finfo_class_entry; |
|||
|
|||
struct finfo_object { |
|||
zend_object zo; |
|||
struct php_fileinfo *ptr; |
|||
}; |
|||
|
|||
#define FILEINFO_DECLARE_INIT_OBJECT(object) \ |
|||
zval *object = getThis(); |
|||
|
|||
#define FILEINFO_REGISTER_OBJECT(_object, _ptr) \ |
|||
{ \ |
|||
struct finfo_object *obj; \ |
|||
obj = (struct finfo_object*)zend_object_store_get_object(_object TSRMLS_CC); \ |
|||
obj->ptr = _ptr; \ |
|||
} |
|||
|
|||
#define FILEINFO_FROM_OBJECT(finfo, object) \ |
|||
{ \ |
|||
struct finfo_object *obj = zend_object_store_get_object(object TSRMLS_CC); \ |
|||
finfo = obj->ptr; \ |
|||
if (!finfo) { \ |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The invalid fileinfo object."); \ |
|||
RETURN_FALSE; \ |
|||
} \ |
|||
} |
|||
|
|||
/* {{{ finfo_objects_dtor |
|||
*/ |
|||
static void finfo_objects_dtor(void *object, zend_object_handle handle TSRMLS_DC) |
|||
{ |
|||
struct finfo_object *intern = (struct finfo_object *) object; |
|||
|
|||
if (intern->ptr) { |
|||
magic_close(intern->ptr->magic); |
|||
efree(intern->ptr); |
|||
} |
|||
|
|||
efree(intern); |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ finfo_objects_new |
|||
*/ |
|||
PHP_FILEINFO_API zend_object_value finfo_objects_new(zend_class_entry *class_type TSRMLS_DC) |
|||
{ |
|||
zend_object_value retval; |
|||
struct finfo_object *intern; |
|||
|
|||
intern = ecalloc(1, sizeof(struct finfo_object)); |
|||
intern->zo.ce = class_type; |
|||
intern->zo.properties = NULL; |
|||
#if ZEND_MODULE_API_NO >= 20050922 |
|||
intern->zo.guards = NULL; |
|||
#else |
|||
intern->zo.in_get = 0; |
|||
intern->zo.in_set = 0; |
|||
#endif |
|||
intern->ptr = NULL; |
|||
|
|||
retval.handle = zend_objects_store_put(intern, finfo_objects_dtor, NULL, NULL TSRMLS_CC); |
|||
retval.handlers = (zend_object_handlers *) &finfo_object_handlers; |
|||
|
|||
return retval; |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ finfo_class_functions |
|||
*/ |
|||
function_entry finfo_class_functions[] = { |
|||
#if PHP_VERSION_ID >= 50200 |
|||
ZEND_ME_MAPPING(finfo, finfo_open, NULL, ZEND_ACC_PUBLIC) |
|||
ZEND_ME_MAPPING(set_flags, finfo_set_flags,NULL, ZEND_ACC_PUBLIC) |
|||
ZEND_ME_MAPPING(file, finfo_file, NULL, ZEND_ACC_PUBLIC) |
|||
ZEND_ME_MAPPING(buffer, finfo_buffer, NULL, ZEND_ACC_PUBLIC) |
|||
#else |
|||
ZEND_ME_MAPPING(finfo, finfo_open, NULL) |
|||
ZEND_ME_MAPPING(set_flags, finfo_set_flags,NULL) |
|||
ZEND_ME_MAPPING(file, finfo_file, NULL) |
|||
ZEND_ME_MAPPING(buffer, finfo_buffer, NULL) |
|||
#endif |
|||
{NULL, NULL, NULL} |
|||
}; |
|||
/* }}} */ |
|||
|
|||
/* }}} */ |
|||
#else |
|||
/* {{{ */ |
|||
#define FILEINFO_REGISTER_OBJECT(_object, _ptr) {} |
|||
#define FILEINFO_FROM_OBJECT(socket_id, object) {} |
|||
|
|||
#define FILEINFO_DECLARE_INIT_OBJECT(object) |
|||
#define object 0 |
|||
|
|||
/* }}} */ |
|||
#endif /* ZEND_ENGINE_2 */ |
|||
|
|||
#define FINFO_SET_OPTION(magic, options) \ |
|||
if (magic_setflags(magic, options) == -1) { \ |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to set option '%ld' %d:%s", \ |
|||
options, magic_errno(magic), magic_error(magic)); \ |
|||
RETURN_FALSE; \ |
|||
} |
|||
|
|||
/* True global resources - no need for thread safety here */ |
|||
static int le_fileinfo; |
|||
/* }}} */ |
|||
|
|||
void finfo_resource_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ |
|||
{ |
|||
if (rsrc->ptr) { |
|||
struct php_fileinfo *finfo = (struct php_fileinfo *) rsrc->ptr; |
|||
magic_close(finfo->magic); |
|||
efree(rsrc->ptr); |
|||
rsrc->ptr = NULL; |
|||
} |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ fileinfo_functions[] |
|||
*/ |
|||
function_entry fileinfo_functions[] = { |
|||
PHP_FE(finfo_open, NULL) |
|||
PHP_FE(finfo_close, NULL) |
|||
PHP_FE(finfo_set_flags, NULL) |
|||
PHP_FE(finfo_file, NULL) |
|||
PHP_FE(finfo_buffer, NULL) |
|||
{NULL, NULL, NULL} |
|||
}; |
|||
/* }}} */ |
|||
|
|||
/* {{{ PHP_MINIT_FUNCTION |
|||
*/ |
|||
PHP_MINIT_FUNCTION(finfo) |
|||
{ |
|||
#ifdef ZEND_ENGINE_2 |
|||
zend_class_entry _finfo_class_entry; |
|||
INIT_CLASS_ENTRY(_finfo_class_entry, "finfo", finfo_class_functions); |
|||
_finfo_class_entry.create_object = finfo_objects_new; |
|||
finfo_class_entry = zend_register_internal_class(&_finfo_class_entry TSRMLS_CC); |
|||
|
|||
/* copy the standard object handlers to you handler table */ |
|||
memcpy(&finfo_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); |
|||
#endif /* ZEND_ENGINE_2 */ |
|||
|
|||
le_fileinfo = zend_register_list_destructors_ex(finfo_resource_destructor, NULL, "file_info", module_number); |
|||
|
|||
REGISTER_LONG_CONSTANT("FILEINFO_NONE", MAGIC_NONE, CONST_CS|CONST_PERSISTENT); |
|||
REGISTER_LONG_CONSTANT("FILEINFO_SYMLINK", MAGIC_SYMLINK, CONST_CS|CONST_PERSISTENT); |
|||
REGISTER_LONG_CONSTANT("FILEINFO_MIME", MAGIC_MIME, CONST_CS|CONST_PERSISTENT); |
|||
REGISTER_LONG_CONSTANT("FILEINFO_COMPRESS", MAGIC_COMPRESS, CONST_CS|CONST_PERSISTENT); |
|||
REGISTER_LONG_CONSTANT("FILEINFO_DEVICES", MAGIC_DEVICES, CONST_CS|CONST_PERSISTENT); |
|||
REGISTER_LONG_CONSTANT("FILEINFO_CONTINUE", MAGIC_CONTINUE, CONST_CS|CONST_PERSISTENT); |
|||
#ifdef MAGIC_PRESERVE_ATIME |
|||
REGISTER_LONG_CONSTANT("FILEINFO_PRESERVE_ATIME", MAGIC_PRESERVE_ATIME, CONST_CS|CONST_PERSISTENT); |
|||
#endif |
|||
#ifdef MAGIC_RAW |
|||
REGISTER_LONG_CONSTANT("FILEINFO_RAW", MAGIC_RAW, CONST_CS|CONST_PERSISTENT); |
|||
#endif |
|||
|
|||
return SUCCESS; |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ fileinfo_module_entry |
|||
*/ |
|||
zend_module_entry fileinfo_module_entry = { |
|||
#if ZEND_MODULE_API_NO >= 20010901 |
|||
STANDARD_MODULE_HEADER, |
|||
#endif |
|||
"fileinfo", |
|||
fileinfo_functions, |
|||
PHP_MINIT(finfo), |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
PHP_MINFO(fileinfo), |
|||
#if ZEND_MODULE_API_NO >= 20010901 |
|||
PHP_FILEINFO_VERSION, |
|||
#endif |
|||
STANDARD_MODULE_PROPERTIES |
|||
}; |
|||
/* }}} */ |
|||
|
|||
#ifdef COMPILE_DL_FILEINFO |
|||
ZEND_GET_MODULE(fileinfo) |
|||
#endif |
|||
|
|||
/* {{{ PHP_MINFO_FUNCTION |
|||
*/ |
|||
PHP_MINFO_FUNCTION(fileinfo) |
|||
{ |
|||
php_info_print_table_start(); |
|||
php_info_print_table_header(2, "fileinfo support", "enabled"); |
|||
php_info_print_table_row(2, "version", PHP_FILEINFO_VERSION); |
|||
php_info_print_table_end(); |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ proto resource finfo_open([int options [, string arg]]) |
|||
Create a new fileinfo resource. */ |
|||
PHP_FUNCTION(finfo_open) |
|||
{ |
|||
long options = MAGIC_NONE; |
|||
char *file = NULL; |
|||
int file_len = 0; |
|||
struct php_fileinfo *finfo; |
|||
FILEINFO_DECLARE_INIT_OBJECT(object) |
|||
char resolved_path[MAXPATHLEN]; |
|||
|
|||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &options, &file, &file_len) == FAILURE) { |
|||
RETURN_FALSE; |
|||
} |
|||
|
|||
if (file_len) { /* user specified filed, perform open_basedir checks */ |
|||
if (!VCWD_REALPATH(file, resolved_path)) { |
|||
RETURN_FALSE; |
|||
} |
|||
file = resolved_path; |
|||
|
|||
if ((PG(safe_mode) && (!php_checkuid(file, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(file TSRMLS_CC)) { |
|||
RETURN_FALSE; |
|||
} |
|||
} |
|||
|
|||
finfo = emalloc(sizeof(struct php_fileinfo)); |
|||
|
|||
finfo->options = options; |
|||
finfo->magic = magic_open(options); |
|||
|
|||
if (finfo->magic == NULL) { |
|||
efree(finfo); |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid mode '%ld'.", options); |
|||
RETURN_FALSE; |
|||
} |
|||
|
|||
if (magic_load(finfo->magic, file) == -1) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database at '%s'.", file); |
|||
magic_close(finfo->magic); |
|||
efree(finfo); |
|||
RETURN_FALSE; |
|||
} |
|||
|
|||
if (object) { |
|||
FILEINFO_REGISTER_OBJECT(object, finfo); |
|||
} else { |
|||
ZEND_REGISTER_RESOURCE(return_value, finfo, le_fileinfo); |
|||
} |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ proto resource finfo_close(resource finfo) |
|||
Close fileinfo resource. */ |
|||
PHP_FUNCTION(finfo_close) |
|||
{ |
|||
struct php_fileinfo *finfo; |
|||
zval *zfinfo; |
|||
|
|||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zfinfo) == FAILURE) { |
|||
RETURN_FALSE; |
|||
} |
|||
ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo); |
|||
|
|||
zend_list_delete(Z_RESVAL_P(zfinfo)); |
|||
|
|||
RETURN_TRUE; |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ proto bool finfo_set_flags(resource finfo, int options) |
|||
Set libmagic configuration options. */ |
|||
PHP_FUNCTION(finfo_set_flags) |
|||
{ |
|||
long options; |
|||
struct php_fileinfo *finfo; |
|||
zval *zfinfo; |
|||
FILEINFO_DECLARE_INIT_OBJECT(object) |
|||
|
|||
if (object) { |
|||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &options) == FAILURE) { |
|||
RETURN_FALSE; |
|||
} |
|||
FILEINFO_FROM_OBJECT(finfo, object); |
|||
} else { |
|||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zfinfo, &options) == FAILURE) { |
|||
RETURN_FALSE; |
|||
} |
|||
ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo); |
|||
} |
|||
|
|||
FINFO_SET_OPTION(finfo->magic, options) |
|||
finfo->options = options; |
|||
|
|||
RETURN_TRUE; |
|||
} |
|||
/* }}} */ |
|||
|
|||
static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ |
|||
{ |
|||
long options = 0; |
|||
char *buffer, *tmp, *ret_val; |
|||
int buffer_len; |
|||
struct php_fileinfo *finfo; |
|||
zval *zfinfo, *zcontext = NULL; |
|||
FILEINFO_DECLARE_INIT_OBJECT(object) |
|||
|
|||
if (object) { |
|||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbr", &buffer, &buffer_len, &options, &zcontext) == FAILURE) { |
|||
RETURN_FALSE; |
|||
} |
|||
FILEINFO_FROM_OBJECT(finfo, object); |
|||
} else { |
|||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lbr", &zfinfo, &buffer, &buffer_len, &options, &zcontext) == FAILURE) { |
|||
RETURN_FALSE; |
|||
} |
|||
ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo); |
|||
} |
|||
|
|||
/* Set options for the current file/buffer. */ |
|||
if (options) { |
|||
FINFO_SET_OPTION(finfo->magic, options) |
|||
} |
|||
|
|||
if (mode) { /* file */ |
|||
/* determine if the file is a local file or remote URL */ |
|||
char *tmp2; |
|||
php_stream_wrapper *wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0 TSRMLS_CC); |
|||
if (wrap && wrap->is_url) { |
|||
#ifdef ZEND_ENGINE_2 |
|||
php_stream_context *context = php_stream_context_from_zval(zcontext, 0); |
|||
#else |
|||
php_stream_context *context = NULL; |
|||
#endif |
|||
php_stream *stream = php_stream_open_wrapper_ex(buffer, "rb", |
|||
ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context); |
|||
if (!stream) { |
|||
RETURN_FALSE; |
|||
} |
|||
buffer_len = php_stream_copy_to_mem(stream, &tmp, HOWMANY, 0); |
|||
php_stream_close(stream); |
|||
|
|||
if (buffer_len == 0) { |
|||
RETURN_FALSE; |
|||
} |
|||
} else { /* local file */ |
|||
char resolved_path[MAXPATHLEN]; |
|||
if (!VCWD_REALPATH(buffer, resolved_path)) { |
|||
RETURN_FALSE; |
|||
} |
|||
|
|||
ret_val = (char *) magic_file(finfo->magic, buffer); |
|||
goto common; |
|||
} |
|||
} else { /* buffer */ |
|||
tmp = buffer; |
|||
} |
|||
|
|||
ret_val = (char *) magic_buffer(finfo->magic, tmp, buffer_len); |
|||
if (mode) { |
|||
efree(tmp); |
|||
} |
|||
common: |
|||
/* Restore options */ |
|||
if (options) { |
|||
FINFO_SET_OPTION(finfo->magic, finfo->options) |
|||
} |
|||
|
|||
if (!ret_val) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s", |
|||
magic_errno(finfo->magic), magic_error(finfo->magic)); |
|||
RETURN_FALSE; |
|||
} else { |
|||
RETURN_STRING(ret_val, 1); |
|||
} |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ proto string finfo_file(resource finfo, char *file_name [, int options [, resource context]]) |
|||
Return information about a file. */ |
|||
PHP_FUNCTION(finfo_file) |
|||
{ |
|||
_php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* {{{ proto string finfo_buffer(resource finfo, char *string [, int options]) |
|||
Return infromation about a string buffer. */ |
|||
PHP_FUNCTION(finfo_buffer) |
|||
{ |
|||
_php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); |
|||
} |
|||
/* }}} */ |
|||
|
|||
/* |
|||
* Local variables: |
|||
* tab-width: 4 |
|||
* c-basic-offset: 4 |
|||
* End: |
|||
* vim600: noet sw=4 ts=4 fdm=marker |
|||
* vim<600: noet sw=4 ts=4 |
|||
*/ |
|||
@ -0,0 +1,170 @@ |
|||
/* |
|||
* Adapted from: apptype.c, Written by Eberhard Mattes and put into the |
|||
* public domain |
|||
* |
|||
* Notes: 1. Qualify the filename so that DosQueryAppType does not do extraneous |
|||
* searches. |
|||
* |
|||
* 2. DosQueryAppType will return FAPPTYP_DOS on a file ending with ".com" |
|||
* (other than an OS/2 exe or Win exe with this name). Eberhard Mattes |
|||
* remarks Tue, 6 Apr 93: Moreover, it reports the type of the (new and very |
|||
* bug ridden) Win Emacs as "OS/2 executable". |
|||
* |
|||
* 3. apptype() uses the filename if given, otherwise a tmp file is created with |
|||
* the contents of buf. If buf is not the complete file, apptype can |
|||
* incorrectly identify the exe type. The "-z" option of "file" is the reason |
|||
* for this ugly code. |
|||
*/ |
|||
|
|||
/* |
|||
* amai: Darrel Hankerson did the changes described here. |
|||
* |
|||
* It remains to check the validity of comments (2.) since it's referred to an |
|||
* "old" OS/2 version. |
|||
* |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: apptype.c,v 1.7 2007/01/12 17:38:27 christos Exp $") |
|||
#endif /* lint */ |
|||
|
|||
#ifdef __EMX__ |
|||
#include <io.h> |
|||
#define INCL_DOSSESMGR |
|||
#define INCL_DOSERRORS |
|||
#define INCL_DOSFILEMGR |
|||
#include <os2.h> |
|||
typedef ULONG APPTYPE; |
|||
|
|||
protected int |
|||
file_os2_apptype(struct magic_set *ms, const char *fn, const void *buf, |
|||
size_t nb) |
|||
{ |
|||
APPTYPE rc, type; |
|||
char path[_MAX_PATH], drive[_MAX_DRIVE], dir[_MAX_DIR], |
|||
fname[_MAX_FNAME], ext[_MAX_EXT]; |
|||
char *filename; |
|||
FILE *fp; |
|||
|
|||
if (fn) |
|||
filename = strdup(fn); |
|||
else if ((filename = tempnam("./", "tmp")) == NULL) { |
|||
file_error(ms, errno, "cannot create tempnam"); |
|||
return -1; |
|||
} |
|||
/* qualify the filename to prevent extraneous searches */ |
|||
_splitpath(filename, drive, dir, fname, ext); |
|||
(void)sprintf(path, "%s%s%s%s", drive, |
|||
(*dir == '\0') ? "./" : dir, |
|||
fname, |
|||
(*ext == '\0') ? "." : ext); |
|||
|
|||
if (fn == NULL) { |
|||
if ((fp = fopen(path, "wb")) == NULL) { |
|||
file_error(ms, errno, "cannot open tmp file `%s'", path); |
|||
return -1; |
|||
} |
|||
if (fwrite(buf, 1, nb, fp) != nb) { |
|||
file_error(ms, errno, "cannot write tmp file `%s'", |
|||
path); |
|||
return -1; |
|||
} |
|||
(void)fclose(fp); |
|||
} |
|||
rc = DosQueryAppType(path, &type); |
|||
|
|||
if (fn == NULL) { |
|||
unlink(path); |
|||
free(filename); |
|||
} |
|||
#if 0 |
|||
if (rc == ERROR_INVALID_EXE_SIGNATURE) |
|||
printf("%s: not an executable file\n", fname); |
|||
else if (rc == ERROR_FILE_NOT_FOUND) |
|||
printf("%s: not found\n", fname); |
|||
else if (rc == ERROR_ACCESS_DENIED) |
|||
printf("%s: access denied\n", fname); |
|||
else if (rc != 0) |
|||
printf("%s: error code = %lu\n", fname, rc); |
|||
else |
|||
#else |
|||
|
|||
/* |
|||
* for our purpose here it's sufficient to just ignore the error and |
|||
* return w/o success (=0) |
|||
*/ |
|||
|
|||
if (rc) |
|||
return (0); |
|||
|
|||
#endif |
|||
|
|||
if (type & FAPPTYP_32BIT) |
|||
if (file_printf(ms, "32-bit ") == -1) |
|||
return -1; |
|||
if (type & FAPPTYP_PHYSDRV) { |
|||
if (file_printf(ms, "physical device driver") == -1) |
|||
return -1; |
|||
} else if (type & FAPPTYP_VIRTDRV) { |
|||
if (file_printf(ms, "virtual device driver") == -1) |
|||
return -1; |
|||
} else if (type & FAPPTYP_DLL) { |
|||
if (type & FAPPTYP_PROTDLL) |
|||
if (file_printf(ms, "protected ") == -1) |
|||
return -1; |
|||
if (file_printf(ms, "DLL") == -1) |
|||
return -1; |
|||
} else if (type & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT)) { |
|||
if (file_printf(ms, "Windows executable") == -1) |
|||
return -1; |
|||
} else if (type & FAPPTYP_DOS) { |
|||
/* |
|||
* The API routine is partially broken on filenames ending |
|||
* ".com". |
|||
*/ |
|||
if (stricmp(ext, ".com") == 0) |
|||
if (strncmp((const char *)buf, "MZ", 2)) |
|||
return (0); |
|||
if (file_printf(ms, "DOS executable") == -1) |
|||
return -1; |
|||
/* ---------------------------------------- */ |
|||
/* Might learn more from the magic(4) entry */ |
|||
if (file_printf(ms, ", magic(4)-> ") == -1) |
|||
return -1; |
|||
return (0); |
|||
/* ---------------------------------------- */ |
|||
} else if (type & FAPPTYP_BOUND) { |
|||
if (file_printf(ms, "bound executable") == -1) |
|||
return -1; |
|||
} else if ((type & 7) == FAPPTYP_WINDOWAPI) { |
|||
if (file_printf(ms, "PM executable") == -1) |
|||
return -1; |
|||
} else if (file_printf(ms, "OS/2 executable") == -1) |
|||
return -1; |
|||
|
|||
switch (type & (FAPPTYP_NOTWINDOWCOMPAT | |
|||
FAPPTYP_WINDOWCOMPAT | |
|||
FAPPTYP_WINDOWAPI)) { |
|||
case FAPPTYP_NOTWINDOWCOMPAT: |
|||
if (file_printf(ms, " [NOTWINDOWCOMPAT]") == -1) |
|||
return -1; |
|||
break; |
|||
case FAPPTYP_WINDOWCOMPAT: |
|||
if (file_printf(ms, " [WINDOWCOMPAT]") == -1) |
|||
return -1; |
|||
break; |
|||
case FAPPTYP_WINDOWAPI: |
|||
if (file_printf(ms, " [WINDOWAPI]") == -1) |
|||
return -1; |
|||
break; |
|||
} |
|||
return 1; |
|||
} |
|||
#endif |
|||
@ -0,0 +1,792 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* ASCII magic -- file types that we know based on keywords |
|||
* that can appear anywhere in the file. |
|||
* |
|||
* Extensively modified by Eric Fischer <enf@pobox.com> in July, 2000, |
|||
* to handle character codes other than ASCII on a unified basis. |
|||
* |
|||
* Joerg Wunsch <joerg@freebsd.org> wrote the original support for 8-bit |
|||
* international characters, now subsumed into this file. |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
#include "magic.h" |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <memory.h> |
|||
#include <ctype.h> |
|||
#include <stdlib.h> |
|||
#ifdef HAVE_UNISTD_H |
|||
#include <unistd.h> |
|||
#endif |
|||
#include "names.h" |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: ascmagic.c,v 1.62 2008/03/01 22:21:48 rrt Exp $") |
|||
#endif /* lint */ |
|||
|
|||
#define MAXLINELEN 300 /* longest sane line length */ |
|||
#define ISSPC(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n' \ |
|||
|| (x) == 0x85 || (x) == '\f') |
|||
|
|||
private int looks_ascii(const unsigned char *, size_t, unichar *, size_t *); |
|||
private int looks_utf8_with_BOM(const unsigned char *, size_t, unichar *, |
|||
size_t *); |
|||
protected int file_looks_utf8(const unsigned char *, size_t, unichar *, size_t *); |
|||
private int looks_ucs16(const unsigned char *, size_t, unichar *, size_t *); |
|||
private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *); |
|||
private int looks_extended(const unsigned char *, size_t, unichar *, size_t *); |
|||
private void from_ebcdic(const unsigned char *, size_t, unsigned char *); |
|||
private int ascmatch(const unsigned char *, const unichar *, size_t); |
|||
private unsigned char *encode_utf8(unsigned char *, size_t, unichar *, size_t); |
|||
|
|||
|
|||
protected int |
|||
file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes) |
|||
{ |
|||
size_t i; |
|||
unsigned char *nbuf = NULL, *utf8_buf = NULL, *utf8_end; |
|||
unichar *ubuf = NULL; |
|||
size_t ulen, mlen; |
|||
const struct names *p; |
|||
int rv = -1; |
|||
int mime = ms->flags & MAGIC_MIME; |
|||
|
|||
const char *code = NULL; |
|||
const char *code_mime = NULL; |
|||
const char *type = NULL; |
|||
const char *subtype = NULL; |
|||
const char *subtype_mime = NULL; |
|||
|
|||
int has_escapes = 0; |
|||
int has_backspace = 0; |
|||
int seen_cr = 0; |
|||
|
|||
int n_crlf = 0; |
|||
int n_lf = 0; |
|||
int n_cr = 0; |
|||
int n_nel = 0; |
|||
|
|||
size_t last_line_end = (size_t)-1; |
|||
int has_long_lines = 0; |
|||
|
|||
/* |
|||
* Undo the NUL-termination kindly provided by process() |
|||
* but leave at least one byte to look at |
|||
*/ |
|||
while (nbytes > 1 && buf[nbytes - 1] == '\0') |
|||
nbytes--; |
|||
|
|||
if ((nbuf = calloc(1, (nbytes + 1) * sizeof(nbuf[0]))) == NULL) |
|||
goto done; |
|||
if ((ubuf = calloc(1, (nbytes + 1) * sizeof(ubuf[0]))) == NULL) |
|||
goto done; |
|||
|
|||
/* |
|||
* Then try to determine whether it's any character code we can |
|||
* identify. Each of these tests, if it succeeds, will leave |
|||
* the text converted into one-unichar-per-character Unicode in |
|||
* ubuf, and the number of characters converted in ulen. |
|||
*/ |
|||
if (looks_ascii(buf, nbytes, ubuf, &ulen)) { |
|||
code = "ASCII"; |
|||
code_mime = "us-ascii"; |
|||
type = "text"; |
|||
} else if (looks_utf8_with_BOM(buf, nbytes, ubuf, &ulen) > 0) { |
|||
code = "UTF-8 Unicode (with BOM)"; |
|||
code_mime = "utf-8"; |
|||
type = "text"; |
|||
} else if (file_looks_utf8(buf, nbytes, ubuf, &ulen) > 1) { |
|||
code = "UTF-8 Unicode"; |
|||
code_mime = "utf-8"; |
|||
type = "text"; |
|||
} else if ((i = looks_ucs16(buf, nbytes, ubuf, &ulen)) != 0) { |
|||
if (i == 1) |
|||
code = "Little-endian UTF-16 Unicode"; |
|||
else |
|||
code = "Big-endian UTF-16 Unicode"; |
|||
|
|||
type = "character data"; |
|||
code_mime = "utf-16"; /* is this defined? */ |
|||
} else if (looks_latin1(buf, nbytes, ubuf, &ulen)) { |
|||
code = "ISO-8859"; |
|||
type = "text"; |
|||
code_mime = "iso-8859-1"; |
|||
} else if (looks_extended(buf, nbytes, ubuf, &ulen)) { |
|||
code = "Non-ISO extended-ASCII"; |
|||
type = "text"; |
|||
code_mime = "unknown"; |
|||
} else { |
|||
from_ebcdic(buf, nbytes, nbuf); |
|||
|
|||
if (looks_ascii(nbuf, nbytes, ubuf, &ulen)) { |
|||
code = "EBCDIC"; |
|||
type = "character data"; |
|||
code_mime = "ebcdic"; |
|||
} else if (looks_latin1(nbuf, nbytes, ubuf, &ulen)) { |
|||
code = "International EBCDIC"; |
|||
type = "character data"; |
|||
code_mime = "ebcdic"; |
|||
} else { |
|||
rv = 0; |
|||
goto done; /* doesn't look like text at all */ |
|||
} |
|||
} |
|||
|
|||
if (nbytes <= 1) { |
|||
rv = 0; |
|||
goto done; |
|||
} |
|||
|
|||
/* Convert ubuf to UTF-8 and try text soft magic */ |
|||
/* If original was ASCII or UTF-8, could use nbuf instead of |
|||
re-converting. */ |
|||
/* malloc size is a conservative overestimate; could be |
|||
re-converting improved, or at least realloced after |
|||
re-converting conversion. */ |
|||
mlen = ulen * 6; |
|||
if ((utf8_buf = malloc(mlen)) == NULL) { |
|||
file_oomem(ms, mlen); |
|||
goto done; |
|||
} |
|||
if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen)) == NULL) |
|||
goto done; |
|||
if (file_softmagic(ms, utf8_buf, utf8_end - utf8_buf, TEXTTEST) != 0) { |
|||
rv = 1; |
|||
goto done; |
|||
} |
|||
|
|||
/* look for tokens from names.h - this is expensive! */ |
|||
if ((ms->flags & MAGIC_NO_CHECK_TOKENS) != 0) |
|||
goto subtype_identified; |
|||
|
|||
i = 0; |
|||
while (i < ulen) { |
|||
size_t end; |
|||
|
|||
/* skip past any leading space */ |
|||
while (i < ulen && ISSPC(ubuf[i])) |
|||
i++; |
|||
if (i >= ulen) |
|||
break; |
|||
|
|||
/* find the next whitespace */ |
|||
for (end = i + 1; end < nbytes; end++) |
|||
if (ISSPC(ubuf[end])) |
|||
break; |
|||
|
|||
/* compare the word thus isolated against the token list */ |
|||
for (p = names; p < names + NNAMES; p++) { |
|||
if (ascmatch((const unsigned char *)p->name, ubuf + i, |
|||
end - i)) { |
|||
subtype = types[p->type].human; |
|||
subtype_mime = types[p->type].mime; |
|||
goto subtype_identified; |
|||
} |
|||
} |
|||
|
|||
i = end; |
|||
} |
|||
|
|||
subtype_identified: |
|||
|
|||
/* Now try to discover other details about the file. */ |
|||
for (i = 0; i < ulen; i++) { |
|||
if (ubuf[i] == '\n') { |
|||
if (seen_cr) |
|||
n_crlf++; |
|||
else |
|||
n_lf++; |
|||
last_line_end = i; |
|||
} else if (seen_cr) |
|||
n_cr++; |
|||
|
|||
seen_cr = (ubuf[i] == '\r'); |
|||
if (seen_cr) |
|||
last_line_end = i; |
|||
|
|||
if (ubuf[i] == 0x85) { /* X3.64/ECMA-43 "next line" character */ |
|||
n_nel++; |
|||
last_line_end = i; |
|||
} |
|||
|
|||
/* If this line is _longer_ than MAXLINELEN, remember it. */ |
|||
if (i > last_line_end + MAXLINELEN) |
|||
has_long_lines = 1; |
|||
|
|||
if (ubuf[i] == '\033') |
|||
has_escapes = 1; |
|||
if (ubuf[i] == '\b') |
|||
has_backspace = 1; |
|||
} |
|||
|
|||
/* Beware, if the data has been truncated, the final CR could have |
|||
been followed by a LF. If we have HOWMANY bytes, it indicates |
|||
that the data might have been truncated, probably even before |
|||
this function was called. */ |
|||
if (seen_cr && nbytes < HOWMANY) |
|||
n_cr++; |
|||
|
|||
if (mime) { |
|||
if (mime & MAGIC_MIME_TYPE) { |
|||
if (subtype_mime) { |
|||
if (file_printf(ms, subtype_mime) == -1) |
|||
goto done; |
|||
} else { |
|||
if (file_printf(ms, "text/plain") == -1) |
|||
goto done; |
|||
} |
|||
} |
|||
|
|||
if ((mime == 0 || mime == MAGIC_MIME) && code_mime) { |
|||
if ((mime & MAGIC_MIME_TYPE) && |
|||
file_printf(ms, " charset=") == -1) |
|||
goto done; |
|||
if (file_printf(ms, code_mime) == -1) |
|||
goto done; |
|||
} |
|||
|
|||
if (mime == MAGIC_MIME_ENCODING) |
|||
file_printf(ms, "binary"); |
|||
} else { |
|||
if (file_printf(ms, code) == -1) |
|||
goto done; |
|||
|
|||
if (subtype) { |
|||
if (file_printf(ms, " ") == -1) |
|||
goto done; |
|||
if (file_printf(ms, subtype) == -1) |
|||
goto done; |
|||
} |
|||
|
|||
if (file_printf(ms, " ") == -1) |
|||
goto done; |
|||
if (file_printf(ms, type) == -1) |
|||
goto done; |
|||
|
|||
if (has_long_lines) |
|||
if (file_printf(ms, ", with very long lines") == -1) |
|||
goto done; |
|||
|
|||
/* |
|||
* Only report line terminators if we find one other than LF, |
|||
* or if we find none at all. |
|||
*/ |
|||
if ((n_crlf == 0 && n_cr == 0 && n_nel == 0 && n_lf == 0) || |
|||
(n_crlf != 0 || n_cr != 0 || n_nel != 0)) { |
|||
if (file_printf(ms, ", with") == -1) |
|||
goto done; |
|||
|
|||
if (n_crlf == 0 && n_cr == 0 && n_nel == 0 && n_lf == 0) { |
|||
if (file_printf(ms, " no") == -1) |
|||
goto done; |
|||
} else { |
|||
if (n_crlf) { |
|||
if (file_printf(ms, " CRLF") == -1) |
|||
goto done; |
|||
if (n_cr || n_lf || n_nel) |
|||
if (file_printf(ms, ",") == -1) |
|||
goto done; |
|||
} |
|||
if (n_cr) { |
|||
if (file_printf(ms, " CR") == -1) |
|||
goto done; |
|||
if (n_lf || n_nel) |
|||
if (file_printf(ms, ",") == -1) |
|||
goto done; |
|||
} |
|||
if (n_lf) { |
|||
if (file_printf(ms, " LF") == -1) |
|||
goto done; |
|||
if (n_nel) |
|||
if (file_printf(ms, ",") == -1) |
|||
goto done; |
|||
} |
|||
if (n_nel) |
|||
if (file_printf(ms, " NEL") == -1) |
|||
goto done; |
|||
} |
|||
|
|||
if (file_printf(ms, " line terminators") == -1) |
|||
goto done; |
|||
} |
|||
|
|||
if (has_escapes) |
|||
if (file_printf(ms, ", with escape sequences") == -1) |
|||
goto done; |
|||
if (has_backspace) |
|||
if (file_printf(ms, ", with overstriking") == -1) |
|||
goto done; |
|||
} |
|||
rv = 1; |
|||
done: |
|||
if (nbuf) |
|||
free(nbuf); |
|||
if (ubuf) |
|||
free(ubuf); |
|||
if (utf8_buf) |
|||
free(utf8_buf); |
|||
|
|||
return rv; |
|||
} |
|||
|
|||
private int |
|||
ascmatch(const unsigned char *s, const unichar *us, size_t ulen) |
|||
{ |
|||
size_t i; |
|||
|
|||
for (i = 0; i < ulen; i++) { |
|||
if (s[i] != us[i]) |
|||
return 0; |
|||
} |
|||
|
|||
if (s[i]) |
|||
return 0; |
|||
else |
|||
return 1; |
|||
} |
|||
|
|||
/* |
|||
* This table reflects a particular philosophy about what constitutes |
|||
* "text," and there is room for disagreement about it. |
|||
* |
|||
* Version 3.31 of the file command considered a file to be ASCII if |
|||
* each of its characters was approved by either the isascii() or |
|||
* isalpha() function. On most systems, this would mean that any |
|||
* file consisting only of characters in the range 0x00 ... 0x7F |
|||
* would be called ASCII text, but many systems might reasonably |
|||
* consider some characters outside this range to be alphabetic, |
|||
* so the file command would call such characters ASCII. It might |
|||
* have been more accurate to call this "considered textual on the |
|||
* local system" than "ASCII." |
|||
* |
|||
* It considered a file to be "International language text" if each |
|||
* of its characters was either an ASCII printing character (according |
|||
* to the real ASCII standard, not the above test), a character in |
|||
* the range 0x80 ... 0xFF, or one of the following control characters: |
|||
* backspace, tab, line feed, vertical tab, form feed, carriage return, |
|||
* escape. No attempt was made to determine the language in which files |
|||
* of this type were written. |
|||
* |
|||
* |
|||
* The table below considers a file to be ASCII if all of its characters |
|||
* are either ASCII printing characters (again, according to the X3.4 |
|||
* standard, not isascii()) or any of the following controls: bell, |
|||
* backspace, tab, line feed, form feed, carriage return, esc, nextline. |
|||
* |
|||
* I include bell because some programs (particularly shell scripts) |
|||
* use it literally, even though it is rare in normal text. I exclude |
|||
* vertical tab because it never seems to be used in real text. I also |
|||
* include, with hesitation, the X3.64/ECMA-43 control nextline (0x85), |
|||
* because that's what the dd EBCDIC->ASCII table maps the EBCDIC newline |
|||
* character to. It might be more appropriate to include it in the 8859 |
|||
* set instead of the ASCII set, but it's got to be included in *something* |
|||
* we recognize or EBCDIC files aren't going to be considered textual. |
|||
* Some old Unix source files use SO/SI (^N/^O) to shift between Greek |
|||
* and Latin characters, so these should possibly be allowed. But they |
|||
* make a real mess on VT100-style displays if they're not paired properly, |
|||
* so we are probably better off not calling them text. |
|||
* |
|||
* A file is considered to be ISO-8859 text if its characters are all |
|||
* either ASCII, according to the above definition, or printing characters |
|||
* from the ISO-8859 8-bit extension, characters 0xA0 ... 0xFF. |
|||
* |
|||
* Finally, a file is considered to be international text from some other |
|||
* character code if its characters are all either ISO-8859 (according to |
|||
* the above definition) or characters in the range 0x80 ... 0x9F, which |
|||
* ISO-8859 considers to be control characters but the IBM PC and Macintosh |
|||
* consider to be printing characters. |
|||
*/ |
|||
|
|||
#define F 0 /* character never appears in text */ |
|||
#define T 1 /* character appears in plain ASCII text */ |
|||
#define I 2 /* character appears in ISO-8859 text */ |
|||
#define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */ |
|||
|
|||
private char text_chars[256] = { |
|||
/* BEL BS HT LF FF CR */ |
|||
F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */ |
|||
/* ESC */ |
|||
F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */ |
|||
/* NEL */ |
|||
X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */ |
|||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */ |
|||
}; |
|||
|
|||
private int |
|||
looks_ascii(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
int t = text_chars[buf[i]]; |
|||
|
|||
if (t != T) |
|||
return 0; |
|||
|
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
private int |
|||
looks_latin1(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
int t = text_chars[buf[i]]; |
|||
|
|||
if (t != T && t != I) |
|||
return 0; |
|||
|
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
private int |
|||
looks_extended(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
int t = text_chars[buf[i]]; |
|||
|
|||
if (t != T && t != I && t != X) |
|||
return 0; |
|||
|
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
/* |
|||
* Encode Unicode string as UTF-8, returning pointer to character |
|||
* after end of string, or NULL if an invalid character is found. |
|||
*/ |
|||
private unsigned char * |
|||
encode_utf8(unsigned char *buf, size_t len, unichar *ubuf, size_t ulen) |
|||
{ |
|||
size_t i; |
|||
unsigned char *end = buf + len; |
|||
|
|||
for (i = 0; i < ulen; i++) { |
|||
if (ubuf[i] <= 0x7f) { |
|||
if (end - buf < 1) |
|||
return NULL; |
|||
*buf++ = (unsigned char)ubuf[i]; |
|||
} else if (ubuf[i] <= 0x7ff) { |
|||
if (end - buf < 2) |
|||
return NULL; |
|||
*buf++ = (unsigned char)((ubuf[i] >> 6) + 0xc0); |
|||
*buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); |
|||
} else if (ubuf[i] <= 0xffff) { |
|||
if (end - buf < 3) |
|||
return NULL; |
|||
*buf++ = (unsigned char)((ubuf[i] >> 12) + 0xe0); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); |
|||
} else if (ubuf[i] <= 0x1fffff) { |
|||
if (end - buf < 4) |
|||
return NULL; |
|||
*buf++ = (unsigned char)((ubuf[i] >> 18) + 0xf0); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); |
|||
} else if (ubuf[i] <= 0x3ffffff) { |
|||
if (end - buf < 5) |
|||
return NULL; |
|||
*buf++ = (unsigned char)((ubuf[i] >> 24) + 0xf8); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); |
|||
} else if (ubuf[i] <= 0x7fffffff) { |
|||
if (end - buf < 6) |
|||
return NULL; |
|||
*buf++ = (unsigned char)((ubuf[i] >> 30) + 0xfc); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 24) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); |
|||
*buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); |
|||
} else /* Invalid character */ |
|||
return NULL; |
|||
} |
|||
|
|||
return buf; |
|||
} |
|||
|
|||
/* |
|||
* Decide whether some text looks like UTF-8. Returns: |
|||
* |
|||
* -1: invalid UTF-8 |
|||
* 0: uses odd control characters, so doesn't look like text |
|||
* 1: 7-bit text |
|||
* 2: definitely UTF-8 text (valid high-bit set bytes) |
|||
* |
|||
* If ubuf is non-NULL on entry, text is decoded into ubuf, *ulen; |
|||
* ubuf must be big enough! |
|||
*/ |
|||
protected int |
|||
file_looks_utf8(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
int n; |
|||
unichar c; |
|||
int gotone = 0, ctrl = 0; |
|||
|
|||
if (ubuf) |
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
if ((buf[i] & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */ |
|||
/* |
|||
* Even if the whole file is valid UTF-8 sequences, |
|||
* still reject it if it uses weird control characters. |
|||
*/ |
|||
|
|||
if (text_chars[buf[i]] != T) |
|||
ctrl = 1; |
|||
|
|||
if (ubuf) |
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} else if ((buf[i] & 0x40) == 0) { /* 10xxxxxx never 1st byte */ |
|||
return -1; |
|||
} else { /* 11xxxxxx begins UTF-8 */ |
|||
int following; |
|||
|
|||
if ((buf[i] & 0x20) == 0) { /* 110xxxxx */ |
|||
c = buf[i] & 0x1f; |
|||
following = 1; |
|||
} else if ((buf[i] & 0x10) == 0) { /* 1110xxxx */ |
|||
c = buf[i] & 0x0f; |
|||
following = 2; |
|||
} else if ((buf[i] & 0x08) == 0) { /* 11110xxx */ |
|||
c = buf[i] & 0x07; |
|||
following = 3; |
|||
} else if ((buf[i] & 0x04) == 0) { /* 111110xx */ |
|||
c = buf[i] & 0x03; |
|||
following = 4; |
|||
} else if ((buf[i] & 0x02) == 0) { /* 1111110x */ |
|||
c = buf[i] & 0x01; |
|||
following = 5; |
|||
} else |
|||
return -1; |
|||
|
|||
for (n = 0; n < following; n++) { |
|||
i++; |
|||
if (i >= nbytes) |
|||
goto done; |
|||
|
|||
if ((buf[i] & 0x80) == 0 || (buf[i] & 0x40)) |
|||
return -1; |
|||
|
|||
c = (c << 6) + (buf[i] & 0x3f); |
|||
} |
|||
|
|||
if (ubuf) |
|||
ubuf[(*ulen)++] = c; |
|||
gotone = 1; |
|||
} |
|||
} |
|||
done: |
|||
return ctrl ? 0 : (gotone ? 2 : 1); |
|||
} |
|||
|
|||
/* |
|||
* Decide whether some text looks like UTF-8 with BOM. If there is no |
|||
* BOM, return -1; otherwise return the result of looks_utf8 on the |
|||
* rest of the text. |
|||
*/ |
|||
private int |
|||
looks_utf8_with_BOM(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
if (nbytes > 3 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf) |
|||
return file_looks_utf8(buf + 3, nbytes - 3, ubuf, ulen); |
|||
else |
|||
return -1; |
|||
} |
|||
|
|||
private int |
|||
looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
int bigend; |
|||
size_t i; |
|||
|
|||
if (nbytes < 2) |
|||
return 0; |
|||
|
|||
if (buf[0] == 0xff && buf[1] == 0xfe) |
|||
bigend = 0; |
|||
else if (buf[0] == 0xfe && buf[1] == 0xff) |
|||
bigend = 1; |
|||
else |
|||
return 0; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 2; i + 1 < nbytes; i += 2) { |
|||
/* XXX fix to properly handle chars > 65536 */ |
|||
|
|||
if (bigend) |
|||
ubuf[(*ulen)++] = buf[i + 1] + 256 * buf[i]; |
|||
else |
|||
ubuf[(*ulen)++] = buf[i] + 256 * buf[i + 1]; |
|||
|
|||
if (ubuf[*ulen - 1] == 0xfffe) |
|||
return 0; |
|||
if (ubuf[*ulen - 1] < 128 && |
|||
text_chars[(size_t)ubuf[*ulen - 1]] != T) |
|||
return 0; |
|||
} |
|||
|
|||
return 1 + bigend; |
|||
} |
|||
|
|||
#undef F |
|||
#undef T |
|||
#undef I |
|||
#undef X |
|||
|
|||
/* |
|||
* This table maps each EBCDIC character to an (8-bit extended) ASCII |
|||
* character, as specified in the rationale for the dd(1) command in |
|||
* draft 11.2 (September, 1991) of the POSIX P1003.2 standard. |
|||
* |
|||
* Unfortunately it does not seem to correspond exactly to any of the |
|||
* five variants of EBCDIC documented in IBM's _Enterprise Systems |
|||
* Architecture/390: Principles of Operation_, SA22-7201-06, Seventh |
|||
* Edition, July, 1999, pp. I-1 - I-4. |
|||
* |
|||
* Fortunately, though, all versions of EBCDIC, including this one, agree |
|||
* on most of the printing characters that also appear in (7-bit) ASCII. |
|||
* Of these, only '|', '!', '~', '^', '[', and ']' are in question at all. |
|||
* |
|||
* Fortunately too, there is general agreement that codes 0x00 through |
|||
* 0x3F represent control characters, 0x41 a nonbreaking space, and the |
|||
* remainder printing characters. |
|||
* |
|||
* This is sufficient to allow us to identify EBCDIC text and to distinguish |
|||
* between old-style and internationalized examples of text. |
|||
*/ |
|||
|
|||
private unsigned char ebcdic_to_ascii[] = { |
|||
0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15, |
|||
16, 17, 18, 19, 157, 133, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31, |
|||
128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7, |
|||
144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26, |
|||
' ', 160, 161, 162, 163, 164, 165, 166, 167, 168, 213, '.', '<', '(', '+', '|', |
|||
'&', 169, 170, 171, 172, 173, 174, 175, 176, 177, '!', '$', '*', ')', ';', '~', |
|||
'-', '/', 178, 179, 180, 181, 182, 183, 184, 185, 203, ',', '%', '_', '>', '?', |
|||
186, 187, 188, 189, 190, 191, 192, 193, 194, '`', ':', '#', '@', '\'','=', '"', |
|||
195, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 196, 197, 198, 199, 200, 201, |
|||
202, 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', '^', 204, 205, 206, 207, 208, |
|||
209, 229, 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 210, 211, 212, '[', 214, 215, |
|||
216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, ']', 230, 231, |
|||
'{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 232, 233, 234, 235, 236, 237, |
|||
'}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 238, 239, 240, 241, 242, 243, |
|||
'\\',159, 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 244, 245, 246, 247, 248, 249, |
|||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 250, 251, 252, 253, 254, 255 |
|||
}; |
|||
|
|||
#ifdef notdef |
|||
/* |
|||
* The following EBCDIC-to-ASCII table may relate more closely to reality, |
|||
* or at least to modern reality. It comes from |
|||
* |
|||
* http://ftp.s390.ibm.com/products/oe/bpxqp9.html |
|||
* |
|||
* and maps the characters of EBCDIC code page 1047 (the code used for |
|||
* Unix-derived software on IBM's 390 systems) to the corresponding |
|||
* characters from ISO 8859-1. |
|||
* |
|||
* If this table is used instead of the above one, some of the special |
|||
* cases for the NEL character can be taken out of the code. |
|||
*/ |
|||
|
|||
private unsigned char ebcdic_1047_to_8859[] = { |
|||
0x00,0x01,0x02,0x03,0x9C,0x09,0x86,0x7F,0x97,0x8D,0x8E,0x0B,0x0C,0x0D,0x0E,0x0F, |
|||
0x10,0x11,0x12,0x13,0x9D,0x0A,0x08,0x87,0x18,0x19,0x92,0x8F,0x1C,0x1D,0x1E,0x1F, |
|||
0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1B,0x88,0x89,0x8A,0x8B,0x8C,0x05,0x06,0x07, |
|||
0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x04,0x98,0x99,0x9A,0x9B,0x14,0x15,0x9E,0x1A, |
|||
0x20,0xA0,0xE2,0xE4,0xE0,0xE1,0xE3,0xE5,0xE7,0xF1,0xA2,0x2E,0x3C,0x28,0x2B,0x7C, |
|||
0x26,0xE9,0xEA,0xEB,0xE8,0xED,0xEE,0xEF,0xEC,0xDF,0x21,0x24,0x2A,0x29,0x3B,0x5E, |
|||
0x2D,0x2F,0xC2,0xC4,0xC0,0xC1,0xC3,0xC5,0xC7,0xD1,0xA6,0x2C,0x25,0x5F,0x3E,0x3F, |
|||
0xF8,0xC9,0xCA,0xCB,0xC8,0xCD,0xCE,0xCF,0xCC,0x60,0x3A,0x23,0x40,0x27,0x3D,0x22, |
|||
0xD8,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0xAB,0xBB,0xF0,0xFD,0xFE,0xB1, |
|||
0xB0,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0xAA,0xBA,0xE6,0xB8,0xC6,0xA4, |
|||
0xB5,0x7E,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0xA1,0xBF,0xD0,0x5B,0xDE,0xAE, |
|||
0xAC,0xA3,0xA5,0xB7,0xA9,0xA7,0xB6,0xBC,0xBD,0xBE,0xDD,0xA8,0xAF,0x5D,0xB4,0xD7, |
|||
0x7B,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xAD,0xF4,0xF6,0xF2,0xF3,0xF5, |
|||
0x7D,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0xB9,0xFB,0xFC,0xF9,0xFA,0xFF, |
|||
0x5C,0xF7,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB2,0xD4,0xD6,0xD2,0xD3,0xD5, |
|||
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xB3,0xDB,0xDC,0xD9,0xDA,0x9F |
|||
}; |
|||
#endif |
|||
|
|||
/* |
|||
* Copy buf[0 ... nbytes-1] into out[], translating EBCDIC to ASCII. |
|||
*/ |
|||
private void |
|||
from_ebcdic(const unsigned char *buf, size_t nbytes, unsigned char *out) |
|||
{ |
|||
size_t i; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
out[i] = ebcdic_to_ascii[buf[i]]; |
|||
} |
|||
} |
|||
@ -0,0 +1,492 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* compress routines: |
|||
* zmagic() - returns 0 if not recognized, uncompresses and prints |
|||
* information if recognized |
|||
* uncompress(method, old, n, newch) - uncompress old into new, |
|||
* using method, return sizeof new |
|||
*/ |
|||
#include "file.h" |
|||
#include "magic.h" |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#ifdef HAVE_UNISTD_H |
|||
#include <unistd.h> |
|||
#endif |
|||
#include <string.h> |
|||
#include <errno.h> |
|||
#include <sys/types.h> |
|||
#include <sys/ioctl.h> |
|||
#ifdef HAVE_SYS_WAIT_H |
|||
#include <sys/wait.h> |
|||
#endif |
|||
#if defined(HAVE_SYS_TIME_H) |
|||
#include <sys/time.h> |
|||
#endif |
|||
#if defined(HAVE_ZLIB_H) && defined(HAVE_LIBZ) |
|||
#define BUILTIN_DECOMPRESS |
|||
#include <zlib.h> |
|||
#endif |
|||
|
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: compress.c,v 1.56 2008/02/07 00:58:52 christos Exp $") |
|||
#endif |
|||
|
|||
private const struct { |
|||
const char magic[8]; |
|||
size_t maglen; |
|||
const char *argv[3]; |
|||
int silent; |
|||
} compr[] = { |
|||
{ "\037\235", 2, { "gzip", "-cdq", NULL }, 1 }, /* compressed */ |
|||
/* Uncompress can get stuck; so use gzip first if we have it |
|||
* Idea from Damien Clark, thanks! */ |
|||
{ "\037\235", 2, { "uncompress", "-c", NULL }, 1 }, /* compressed */ |
|||
{ "\037\213", 2, { "gzip", "-cdq", NULL }, 1 }, /* gzipped */ |
|||
{ "\037\236", 2, { "gzip", "-cdq", NULL }, 1 }, /* frozen */ |
|||
{ "\037\240", 2, { "gzip", "-cdq", NULL }, 1 }, /* SCO LZH */ |
|||
/* the standard pack utilities do not accept standard input */ |
|||
{ "\037\036", 2, { "gzip", "-cdq", NULL }, 0 }, /* packed */ |
|||
{ "PK\3\4", 4, { "gzip", "-cdq", NULL }, 1 }, /* pkzipped, */ |
|||
/* ...only first file examined */ |
|||
{ "BZh", 3, { "bzip2", "-cd", NULL }, 1 }, /* bzip2-ed */ |
|||
}; |
|||
|
|||
private size_t ncompr = sizeof(compr) / sizeof(compr[0]); |
|||
|
|||
#define NODATA ((size_t)~0) |
|||
|
|||
|
|||
private ssize_t swrite(int, const void *, size_t); |
|||
private size_t uncompressbuf(struct magic_set *, int, size_t, |
|||
const unsigned char *, unsigned char **, size_t); |
|||
#ifdef BUILTIN_DECOMPRESS |
|||
private size_t uncompressgzipped(struct magic_set *, const unsigned char *, |
|||
unsigned char **, size_t); |
|||
#endif |
|||
|
|||
protected int |
|||
file_zmagic(struct magic_set *ms, int fd, const char *name, |
|||
const unsigned char *buf, size_t nbytes) |
|||
{ |
|||
unsigned char *newbuf = NULL; |
|||
size_t i, nsz; |
|||
int rv = 0; |
|||
int mime = ms->flags & MAGIC_MIME; |
|||
|
|||
if ((ms->flags & MAGIC_COMPRESS) == 0) |
|||
return 0; |
|||
|
|||
for (i = 0; i < ncompr; i++) { |
|||
if (nbytes < compr[i].maglen) |
|||
continue; |
|||
if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0 && |
|||
(nsz = uncompressbuf(ms, fd, i, buf, &newbuf, |
|||
nbytes)) != NODATA) { |
|||
ms->flags &= ~MAGIC_COMPRESS; |
|||
rv = -1; |
|||
if (file_buffer(ms, -1, name, newbuf, nsz) == -1) |
|||
goto error; |
|||
|
|||
if (mime == MAGIC_MIME || mime == 0) { |
|||
if (file_printf(ms, mime ? |
|||
" compressed-encoding=" : " (") == -1) |
|||
goto error; |
|||
} |
|||
|
|||
if ((mime == 0 || mime & MAGIC_MIME_ENCODING) && |
|||
file_buffer(ms, -1, NULL, buf, nbytes) == -1) |
|||
goto error; |
|||
|
|||
if (!mime && file_printf(ms, ")") == -1) |
|||
goto error; |
|||
rv = 1; |
|||
break; |
|||
} |
|||
} |
|||
error: |
|||
if (newbuf) |
|||
free(newbuf); |
|||
ms->flags |= MAGIC_COMPRESS; |
|||
return rv; |
|||
} |
|||
|
|||
/* |
|||
* `safe' write for sockets and pipes. |
|||
*/ |
|||
private ssize_t |
|||
swrite(int fd, const void *buf, size_t n) |
|||
{ |
|||
int rv; |
|||
size_t rn = n; |
|||
|
|||
do |
|||
switch (rv = write(fd, buf, n)) { |
|||
case -1: |
|||
if (errno == EINTR) |
|||
continue; |
|||
return -1; |
|||
default: |
|||
n -= rv; |
|||
buf = ((const char *)buf) + rv; |
|||
break; |
|||
} |
|||
while (n > 0); |
|||
return rn; |
|||
} |
|||
|
|||
|
|||
/* |
|||
* `safe' read for sockets and pipes. |
|||
*/ |
|||
protected ssize_t |
|||
sread(int fd, void *buf, size_t n, int canbepipe) |
|||
{ |
|||
int rv, cnt; |
|||
#ifdef FIONREAD |
|||
int t = 0; |
|||
#endif |
|||
size_t rn = n; |
|||
|
|||
if (fd == STDIN_FILENO) |
|||
goto nocheck; |
|||
|
|||
#ifdef FIONREAD |
|||
if ((canbepipe && (ioctl(fd, FIONREAD, &t) == -1)) || (t == 0)) { |
|||
#ifdef FD_ZERO |
|||
for (cnt = 0;; cnt++) { |
|||
fd_set check; |
|||
struct timeval tout = {0, 100 * 1000}; |
|||
int selrv; |
|||
|
|||
FD_ZERO(&check); |
|||
FD_SET(fd, &check); |
|||
|
|||
/* |
|||
* Avoid soft deadlock: do not read if there |
|||
* is nothing to read from sockets and pipes. |
|||
*/ |
|||
selrv = select(fd + 1, &check, NULL, NULL, &tout); |
|||
if (selrv == -1) { |
|||
if (errno == EINTR || errno == EAGAIN) |
|||
continue; |
|||
} else if (selrv == 0 && cnt >= 5) { |
|||
return 0; |
|||
} else |
|||
break; |
|||
} |
|||
#endif |
|||
(void)ioctl(fd, FIONREAD, &t); |
|||
} |
|||
|
|||
if (t > 0 && (size_t)t < n) { |
|||
n = t; |
|||
rn = n; |
|||
} |
|||
#endif |
|||
|
|||
nocheck: |
|||
do |
|||
switch ((rv = read(fd, buf, n))) { |
|||
case -1: |
|||
if (errno == EINTR) |
|||
continue; |
|||
return -1; |
|||
case 0: |
|||
return rn - n; |
|||
default: |
|||
n -= rv; |
|||
buf = ((char *)buf) + rv; |
|||
break; |
|||
} |
|||
while (n > 0); |
|||
return rn; |
|||
} |
|||
|
|||
protected int |
|||
file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, |
|||
size_t nbytes) |
|||
{ |
|||
char buf[4096]; |
|||
int r, tfd; |
|||
|
|||
(void)strcpy(buf, "/tmp/file.XXXXXX"); |
|||
#ifndef HAVE_MKSTEMP |
|||
{ |
|||
char *ptr = mktemp(buf); |
|||
tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600); |
|||
r = errno; |
|||
(void)unlink(ptr); |
|||
errno = r; |
|||
} |
|||
#else |
|||
tfd = mkstemp(buf); |
|||
r = errno; |
|||
(void)unlink(buf); |
|||
errno = r; |
|||
#endif |
|||
if (tfd == -1) { |
|||
file_error(ms, errno, |
|||
"cannot create temporary file for pipe copy"); |
|||
return -1; |
|||
} |
|||
|
|||
if (swrite(tfd, startbuf, nbytes) != (ssize_t)nbytes) |
|||
r = 1; |
|||
else { |
|||
while ((r = sread(fd, buf, sizeof(buf), 1)) > 0) |
|||
if (swrite(tfd, buf, (size_t)r) != r) |
|||
break; |
|||
} |
|||
|
|||
switch (r) { |
|||
case -1: |
|||
file_error(ms, errno, "error copying from pipe to temp file"); |
|||
return -1; |
|||
case 0: |
|||
break; |
|||
default: |
|||
file_error(ms, errno, "error while writing to temp file"); |
|||
return -1; |
|||
} |
|||
|
|||
/* |
|||
* We duplicate the file descriptor, because fclose on a |
|||
* tmpfile will delete the file, but any open descriptors |
|||
* can still access the phantom inode. |
|||
*/ |
|||
if ((fd = dup2(tfd, fd)) == -1) { |
|||
file_error(ms, errno, "could not dup descriptor for temp file"); |
|||
return -1; |
|||
} |
|||
(void)close(tfd); |
|||
if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { |
|||
file_badseek(ms); |
|||
return -1; |
|||
} |
|||
return fd; |
|||
} |
|||
|
|||
#ifdef BUILTIN_DECOMPRESS |
|||
|
|||
#define FHCRC (1 << 1) |
|||
#define FEXTRA (1 << 2) |
|||
#define FNAME (1 << 3) |
|||
#define FCOMMENT (1 << 4) |
|||
|
|||
private size_t |
|||
uncompressgzipped(struct magic_set *ms, const unsigned char *old, |
|||
unsigned char **newch, size_t n) |
|||
{ |
|||
unsigned char flg = old[3]; |
|||
size_t data_start = 10; |
|||
z_stream z; |
|||
int rc; |
|||
|
|||
if (flg & FEXTRA) { |
|||
if (data_start+1 >= n) |
|||
return 0; |
|||
data_start += 2 + old[data_start] + old[data_start + 1] * 256; |
|||
} |
|||
if (flg & FNAME) { |
|||
while(data_start < n && old[data_start]) |
|||
data_start++; |
|||
data_start++; |
|||
} |
|||
if(flg & FCOMMENT) { |
|||
while(data_start < n && old[data_start]) |
|||
data_start++; |
|||
data_start++; |
|||
} |
|||
if(flg & FHCRC) |
|||
data_start += 2; |
|||
|
|||
if (data_start >= n) |
|||
return 0; |
|||
if ((*newch = (unsigned char *)malloc(HOWMANY + 1)) == NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
/* XXX: const castaway, via strchr */ |
|||
z.next_in = (Bytef *)strchr((const char *)old + data_start, |
|||
old[data_start]); |
|||
z.avail_in = n - data_start; |
|||
z.next_out = *newch; |
|||
z.avail_out = HOWMANY; |
|||
z.zalloc = Z_NULL; |
|||
z.zfree = Z_NULL; |
|||
z.opaque = Z_NULL; |
|||
|
|||
rc = inflateInit2(&z, -15); |
|||
if (rc != Z_OK) { |
|||
file_error(ms, 0, "zlib: %s", z.msg); |
|||
return 0; |
|||
} |
|||
|
|||
rc = inflate(&z, Z_SYNC_FLUSH); |
|||
if (rc != Z_OK && rc != Z_STREAM_END) { |
|||
file_error(ms, 0, "zlib: %s", z.msg); |
|||
return 0; |
|||
} |
|||
|
|||
n = (size_t)z.total_out; |
|||
(void)inflateEnd(&z); |
|||
|
|||
/* let's keep the nul-terminate tradition */ |
|||
(*newch)[n] = '\0'; |
|||
|
|||
return n; |
|||
} |
|||
#endif |
|||
|
|||
private size_t |
|||
uncompressbuf(struct magic_set *ms, int fd, size_t method, |
|||
const unsigned char *old, unsigned char **newch, size_t n) |
|||
{ |
|||
int fdin[2], fdout[2]; |
|||
int r; |
|||
|
|||
#ifdef BUILTIN_DECOMPRESS |
|||
/* FIXME: This doesn't cope with bzip2 */ |
|||
if (method == 2) |
|||
return uncompressgzipped(ms, old, newch, n); |
|||
#endif |
|||
(void)fflush(stdout); |
|||
(void)fflush(stderr); |
|||
|
|||
if ((fd != -1 && pipe(fdin) == -1) || pipe(fdout) == -1) { |
|||
file_error(ms, errno, "cannot create pipe"); |
|||
return NODATA; |
|||
} |
|||
switch (fork()) { |
|||
case 0: /* child */ |
|||
(void) close(0); |
|||
if (fd != -1) { |
|||
(void) dup(fd); |
|||
(void) lseek(0, (off_t)0, SEEK_SET); |
|||
} else { |
|||
(void) dup(fdin[0]); |
|||
(void) close(fdin[0]); |
|||
(void) close(fdin[1]); |
|||
} |
|||
|
|||
(void) close(1); |
|||
(void) dup(fdout[1]); |
|||
(void) close(fdout[0]); |
|||
(void) close(fdout[1]); |
|||
#ifndef DEBUG |
|||
if (compr[method].silent) |
|||
(void)close(2); |
|||
#endif |
|||
|
|||
(void)execvp(compr[method].argv[0], |
|||
(char *const *)(intptr_t)compr[method].argv); |
|||
#ifdef DEBUG |
|||
(void)fprintf(stderr, "exec `%s' failed (%s)\n", |
|||
compr[method].argv[0], strerror(errno)); |
|||
#endif |
|||
exit(1); |
|||
/*NOTREACHED*/ |
|||
case -1: |
|||
file_error(ms, errno, "could not fork"); |
|||
return NODATA; |
|||
|
|||
default: /* parent */ |
|||
(void) close(fdout[1]); |
|||
if (fd == -1) { |
|||
(void) close(fdin[0]); |
|||
/* |
|||
* fork again, to avoid blocking because both |
|||
* pipes filled |
|||
*/ |
|||
switch (fork()) { |
|||
case 0: /* child */ |
|||
(void)close(fdout[0]); |
|||
if (swrite(fdin[1], old, n) != (ssize_t)n) { |
|||
#ifdef DEBUG |
|||
(void)fprintf(stderr, |
|||
"Write failed (%s)\n", |
|||
strerror(errno)); |
|||
#endif |
|||
exit(1); |
|||
} |
|||
exit(0); |
|||
/*NOTREACHED*/ |
|||
|
|||
case -1: |
|||
#ifdef DEBUG |
|||
(void)fprintf(stderr, "Fork failed (%s)\n", |
|||
strerror(errno)); |
|||
#endif |
|||
exit(1); |
|||
/*NOTREACHED*/ |
|||
|
|||
default: /* parent */ |
|||
break; |
|||
} |
|||
(void) close(fdin[1]); |
|||
fdin[1] = -1; |
|||
} |
|||
|
|||
if ((*newch = (unsigned char *) malloc(HOWMANY + 1)) == NULL) { |
|||
#ifdef DEBUG |
|||
(void)fprintf(stderr, "Malloc failed (%s)\n", |
|||
strerror(errno)); |
|||
#endif |
|||
n = 0; |
|||
goto err; |
|||
} |
|||
if ((r = sread(fdout[0], *newch, HOWMANY, 0)) <= 0) { |
|||
#ifdef DEBUG |
|||
(void)fprintf(stderr, "Read failed (%s)\n", |
|||
strerror(errno)); |
|||
#endif |
|||
free(*newch); |
|||
n = 0; |
|||
newch[0] = '\0'; |
|||
goto err; |
|||
} else { |
|||
n = r; |
|||
} |
|||
/* NUL terminate, as every buffer is handled here. */ |
|||
(*newch)[n] = '\0'; |
|||
err: |
|||
if (fdin[1] != -1) |
|||
(void) close(fdin[1]); |
|||
(void) close(fdout[0]); |
|||
#ifdef WNOHANG |
|||
while (waitpid(-1, NULL, WNOHANG) != -1) |
|||
continue; |
|||
#else |
|||
(void)wait(NULL); |
|||
#endif |
|||
return n; |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
#include <php_config.h> |
|||
#ifdef HAVE_CONFIG_H |
|||
#include "../config.h" |
|||
#endif |
|||
#define PHP_BUNDLE |
|||
@ -0,0 +1,67 @@ |
|||
/* |
|||
* Copyright (c) Christos Zoulas 2008. |
|||
* All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
if (nbytes <= sizeof(elfhdr)) |
|||
return 0; |
|||
|
|||
u.l = 1; |
|||
(void)memcpy(&elfhdr, buf, sizeof elfhdr); |
|||
swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA]; |
|||
|
|||
type = elf_getu16(swap, elfhdr.e_type); |
|||
switch (type) { |
|||
#ifdef ELFCORE |
|||
case ET_CORE: |
|||
if (dophn_core(ms, class, swap, fd, |
|||
(off_t)elf_getu(swap, elfhdr.e_phoff), |
|||
elf_getu16(swap, elfhdr.e_phnum), |
|||
(size_t)elf_getu16(swap, elfhdr.e_phentsize), |
|||
fsize, &flags) == -1) |
|||
return -1; |
|||
break; |
|||
#endif |
|||
case ET_EXEC: |
|||
case ET_DYN: |
|||
if (dophn_exec(ms, class, swap, fd, |
|||
(off_t)elf_getu(swap, elfhdr.e_phoff), |
|||
elf_getu16(swap, elfhdr.e_phnum), |
|||
(size_t)elf_getu16(swap, elfhdr.e_phentsize), |
|||
fsize, &flags) == -1) |
|||
return -1; |
|||
/*FALLTHROUGH*/ |
|||
case ET_REL: |
|||
if (doshn(ms, class, swap, fd, |
|||
(off_t)elf_getu(swap, elfhdr.e_shoff), |
|||
elf_getu16(swap, elfhdr.e_shnum), |
|||
(size_t)elf_getu16(swap, elfhdr.e_shentsize), |
|||
&flags) == -1) |
|||
return -1; |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
} |
|||
return 1; |
|||
@ -0,0 +1,481 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* file - find type of a file or files - main program. |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
#include "magic.h" |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
#include <string.h> |
|||
#include <sys/types.h> |
|||
#include <sys/param.h> /* for MAXPATHLEN */ |
|||
#include <sys/stat.h> |
|||
#ifdef RESTORE_TIME |
|||
# if (__COHERENT__ >= 0x420) |
|||
# include <sys/utime.h> |
|||
# else |
|||
# ifdef USE_UTIMES |
|||
# include <sys/time.h> |
|||
# else |
|||
# include <utime.h> |
|||
# endif |
|||
# endif |
|||
#endif |
|||
#ifdef HAVE_UNISTD_H |
|||
#include <unistd.h> /* for read() */ |
|||
#endif |
|||
#ifdef HAVE_LOCALE_H |
|||
#include <locale.h> |
|||
#endif |
|||
#ifdef HAVE_WCHAR_H |
|||
#include <wchar.h> |
|||
#endif |
|||
|
|||
#include <getopt.h> |
|||
#ifndef HAVE_GETOPT_LONG |
|||
int getopt_long(int argc, char * const *argv, const char *optstring, const struct option *longopts, int *longindex); |
|||
#endif |
|||
|
|||
#include <netinet/in.h> /* for byte swapping */ |
|||
|
|||
#include "patchlevel.h" |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: file.c,v 1.119 2008/02/07 00:58:52 christos Exp $") |
|||
#endif /* lint */ |
|||
|
|||
|
|||
#ifdef S_IFLNK |
|||
#define SYMLINKFLAG "Lh" |
|||
#else |
|||
#define SYMLINKFLAG "" |
|||
#endif |
|||
|
|||
# define USAGE "Usage: %s [-bcik" SYMLINKFLAG "nNrsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] file...\n %s -C -m magicfiles\n" |
|||
|
|||
#ifndef MAXPATHLEN |
|||
#define MAXPATHLEN 512 |
|||
#endif |
|||
|
|||
private int /* Global command-line options */ |
|||
bflag = 0, /* brief output format */ |
|||
nopad = 0, /* Don't pad output */ |
|||
nobuffer = 0, /* Do not buffer stdout */ |
|||
nulsep = 0; /* Append '\0' to the separator */ |
|||
|
|||
private const char *magicfile = 0; /* where the magic is */ |
|||
private const char *default_magicfile = MAGIC; |
|||
private const char *separator = ":"; /* Default field separator */ |
|||
|
|||
private char *progname; /* used throughout */ |
|||
|
|||
private struct magic_set *magic; |
|||
|
|||
private void unwrap(char *); |
|||
private void usage(void); |
|||
private void help(void); |
|||
|
|||
int main(int, char *[]); |
|||
private void process(const char *, int); |
|||
private void load(const char *, int); |
|||
|
|||
|
|||
/* |
|||
* main - parse arguments and handle options |
|||
*/ |
|||
int |
|||
main(int argc, char *argv[]) |
|||
{ |
|||
int c; |
|||
size_t i; |
|||
int action = 0, didsomefiles = 0, errflg = 0; |
|||
int flags = 0; |
|||
char *home, *usermagic; |
|||
struct stat sb; |
|||
static const char hmagic[] = "/.magic"; |
|||
#define OPTSTRING "bcCde:f:F:hikLm:nNprsvz0" |
|||
int longindex; |
|||
static const struct option long_options[] = |
|||
{ |
|||
#define OPT(shortname, longname, opt, doc) \ |
|||
{longname, opt, NULL, shortname}, |
|||
#define OPT_LONGONLY(longname, opt, doc) \ |
|||
{longname, opt, NULL, 0}, |
|||
#include "file_opts.h" |
|||
#undef OPT |
|||
#undef OPT_LONGONLY |
|||
{0, 0, NULL, 0} |
|||
}; |
|||
|
|||
static const struct { |
|||
const char *name; |
|||
int value; |
|||
} nv[] = { |
|||
{ "apptype", MAGIC_NO_CHECK_APPTYPE }, |
|||
{ "ascii", MAGIC_NO_CHECK_ASCII }, |
|||
{ "compress", MAGIC_NO_CHECK_COMPRESS }, |
|||
{ "elf", MAGIC_NO_CHECK_ELF }, |
|||
{ "soft", MAGIC_NO_CHECK_SOFT }, |
|||
{ "tar", MAGIC_NO_CHECK_TAR }, |
|||
{ "tokens", MAGIC_NO_CHECK_TOKENS }, |
|||
}; |
|||
|
|||
/* makes islower etc work for other langs */ |
|||
(void)setlocale(LC_CTYPE, ""); |
|||
|
|||
#ifdef __EMX__ |
|||
/* sh-like wildcard expansion! Shouldn't hurt at least ... */ |
|||
_wildcard(&argc, &argv); |
|||
#endif |
|||
|
|||
if ((progname = strrchr(argv[0], '/')) != NULL) |
|||
progname++; |
|||
else |
|||
progname = argv[0]; |
|||
|
|||
magicfile = default_magicfile; |
|||
if ((usermagic = getenv("MAGIC")) != NULL) |
|||
magicfile = usermagic; |
|||
else |
|||
if ((home = getenv("HOME")) != NULL) { |
|||
if ((usermagic = malloc(strlen(home) |
|||
+ sizeof(hmagic))) != NULL) { |
|||
(void)strcpy(usermagic, home); |
|||
(void)strcat(usermagic, hmagic); |
|||
if (stat(usermagic, &sb)<0) |
|||
free(usermagic); |
|||
else |
|||
magicfile = usermagic; |
|||
} |
|||
} |
|||
|
|||
#ifdef S_IFLNK |
|||
flags |= getenv("POSIXLY_CORRECT") ? MAGIC_SYMLINK : 0; |
|||
#endif |
|||
while ((c = getopt_long(argc, argv, OPTSTRING, long_options, |
|||
&longindex)) != -1) |
|||
switch (c) { |
|||
case 0 : |
|||
switch (longindex) { |
|||
case 0: |
|||
help(); |
|||
break; |
|||
case 10: |
|||
flags |= MAGIC_MIME_TYPE; |
|||
break; |
|||
case 11: |
|||
flags |= MAGIC_MIME_ENCODING; |
|||
break; |
|||
} |
|||
break; |
|||
case '0': |
|||
nulsep = 1; |
|||
break; |
|||
case 'b': |
|||
bflag++; |
|||
break; |
|||
case 'c': |
|||
action = FILE_CHECK; |
|||
break; |
|||
case 'C': |
|||
action = FILE_COMPILE; |
|||
break; |
|||
case 'd': |
|||
flags |= MAGIC_DEBUG|MAGIC_CHECK; |
|||
break; |
|||
case 'e': |
|||
for (i = 0; i < sizeof(nv) / sizeof(nv[0]); i++) |
|||
if (strcmp(nv[i].name, optarg) == 0) |
|||
break; |
|||
|
|||
if (i == sizeof(nv) / sizeof(nv[0])) |
|||
errflg++; |
|||
else |
|||
flags |= nv[i].value; |
|||
break; |
|||
|
|||
case 'f': |
|||
if(action) |
|||
usage(); |
|||
load(magicfile, flags); |
|||
unwrap(optarg); |
|||
++didsomefiles; |
|||
break; |
|||
case 'F': |
|||
separator = optarg; |
|||
break; |
|||
case 'i': |
|||
flags |= MAGIC_MIME; |
|||
break; |
|||
case 'k': |
|||
flags |= MAGIC_CONTINUE; |
|||
break; |
|||
case 'm': |
|||
magicfile = optarg; |
|||
break; |
|||
case 'n': |
|||
++nobuffer; |
|||
break; |
|||
case 'N': |
|||
++nopad; |
|||
break; |
|||
#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) |
|||
case 'p': |
|||
flags |= MAGIC_PRESERVE_ATIME; |
|||
break; |
|||
#endif |
|||
case 'r': |
|||
flags |= MAGIC_RAW; |
|||
break; |
|||
case 's': |
|||
flags |= MAGIC_DEVICES; |
|||
break; |
|||
case 'v': |
|||
(void)fprintf(stderr, "%s-%d.%.2d\n", progname, |
|||
FILE_VERSION_MAJOR, patchlevel); |
|||
(void)fprintf(stderr, "magic file from %s\n", |
|||
magicfile); |
|||
return 1; |
|||
case 'z': |
|||
flags |= MAGIC_COMPRESS; |
|||
break; |
|||
#ifdef S_IFLNK |
|||
case 'L': |
|||
flags |= MAGIC_SYMLINK; |
|||
break; |
|||
case 'h': |
|||
flags &= ~MAGIC_SYMLINK; |
|||
break; |
|||
#endif |
|||
case '?': |
|||
default: |
|||
errflg++; |
|||
break; |
|||
} |
|||
|
|||
if (errflg) { |
|||
usage(); |
|||
} |
|||
|
|||
switch(action) { |
|||
case FILE_CHECK: |
|||
case FILE_COMPILE: |
|||
magic = magic_open(flags|MAGIC_CHECK); |
|||
if (magic == NULL) { |
|||
(void)fprintf(stderr, "%s: %s\n", progname, |
|||
strerror(errno)); |
|||
return 1; |
|||
} |
|||
c = action == FILE_CHECK ? magic_check(magic, magicfile) : |
|||
magic_compile(magic, magicfile); |
|||
if (c == -1) { |
|||
(void)fprintf(stderr, "%s: %s\n", progname, |
|||
magic_error(magic)); |
|||
return -1; |
|||
} |
|||
return 0; |
|||
default: |
|||
load(magicfile, flags); |
|||
break; |
|||
} |
|||
|
|||
if (optind == argc) { |
|||
if (!didsomefiles) { |
|||
usage(); |
|||
} |
|||
} |
|||
else { |
|||
size_t j, wid, nw; |
|||
for (wid = 0, j = (size_t)optind; j < (size_t)argc; j++) { |
|||
nw = file_mbswidth(argv[j]); |
|||
if (nw > wid) |
|||
wid = nw; |
|||
} |
|||
/* |
|||
* If bflag is only set twice, set it depending on |
|||
* number of files [this is undocumented, and subject to change] |
|||
*/ |
|||
if (bflag == 2) { |
|||
bflag = optind >= argc - 1; |
|||
} |
|||
for (; optind < argc; optind++) |
|||
process(argv[optind], wid); |
|||
} |
|||
|
|||
c = magic->haderr ? 1 : 0; |
|||
magic_close(magic); |
|||
return c; |
|||
} |
|||
|
|||
|
|||
private void |
|||
/*ARGSUSED*/ |
|||
load(const char *m, int flags) |
|||
{ |
|||
if (magic || m == NULL) |
|||
return; |
|||
magic = magic_open(flags); |
|||
if (magic == NULL) { |
|||
(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno)); |
|||
exit(1); |
|||
} |
|||
if (magic_load(magic, magicfile) == -1) { |
|||
(void)fprintf(stderr, "%s: %s\n", |
|||
progname, magic_error(magic)); |
|||
exit(1); |
|||
} |
|||
} |
|||
|
|||
/* |
|||
* unwrap -- read a file of filenames, do each one. |
|||
*/ |
|||
private void |
|||
unwrap(char *fn) |
|||
{ |
|||
char buf[MAXPATHLEN]; |
|||
FILE *f; |
|||
int wid = 0, cwid; |
|||
|
|||
if (strcmp("-", fn) == 0) { |
|||
f = stdin; |
|||
wid = 1; |
|||
} else { |
|||
if ((f = fopen(fn, "r")) == NULL) { |
|||
(void)fprintf(stderr, "%s: Cannot open `%s' (%s).\n", |
|||
progname, fn, strerror(errno)); |
|||
exit(1); |
|||
} |
|||
|
|||
while (fgets(buf, MAXPATHLEN, f) != NULL) { |
|||
buf[strcspn(buf, "\n")] = '\0'; |
|||
cwid = file_mbswidth(buf); |
|||
if (cwid > wid) |
|||
wid = cwid; |
|||
} |
|||
|
|||
rewind(f); |
|||
} |
|||
|
|||
while (fgets(buf, sizeof(buf), f) != NULL) { |
|||
buf[strcspn(buf, "\n")] = '\0'; |
|||
process(buf, wid); |
|||
if(nobuffer) |
|||
(void)fflush(stdout); |
|||
} |
|||
|
|||
(void)fclose(f); |
|||
} |
|||
|
|||
/* |
|||
* Called for each input file on the command line (or in a list of files) |
|||
*/ |
|||
private void |
|||
process(const char *inname, int wid) |
|||
{ |
|||
const char *type; |
|||
int std_in = strcmp(inname, "-") == 0; |
|||
|
|||
if (wid > 0 && !bflag) { |
|||
(void)printf("%s", std_in ? "/dev/stdin" : inname); |
|||
if (nulsep) |
|||
(void)putc('\0', stdout); |
|||
else |
|||
(void)printf("%s", separator); |
|||
(void)printf("%*s ", |
|||
(int) (nopad ? 0 : (wid - file_mbswidth(inname))), ""); |
|||
} |
|||
|
|||
type = magic_file(magic, std_in ? NULL : inname); |
|||
if (type == NULL) |
|||
(void)printf("ERROR: %s\n", magic_error(magic)); |
|||
else |
|||
(void)printf("%s\n", type); |
|||
} |
|||
|
|||
size_t |
|||
file_mbswidth(const char *s) |
|||
{ |
|||
#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) |
|||
size_t bytesconsumed, old_n, n, width = 0; |
|||
mbstate_t state; |
|||
wchar_t nextchar; |
|||
(void)memset(&state, 0, sizeof(mbstate_t)); |
|||
old_n = n = strlen(s); |
|||
|
|||
while (n > 0) { |
|||
bytesconsumed = mbrtowc(&nextchar, s, n, &state); |
|||
if (bytesconsumed == (size_t)(-1) || |
|||
bytesconsumed == (size_t)(-2)) { |
|||
/* Something went wrong, return something reasonable */ |
|||
return old_n; |
|||
} |
|||
if (s[0] == '\n') { |
|||
/* |
|||
* do what strlen() would do, so that caller |
|||
* is always right |
|||
*/ |
|||
width++; |
|||
} else |
|||
width += wcwidth(nextchar); |
|||
|
|||
s += bytesconsumed, n -= bytesconsumed; |
|||
} |
|||
return width; |
|||
#else |
|||
return strlen(s); |
|||
#endif |
|||
} |
|||
|
|||
private void |
|||
usage(void) |
|||
{ |
|||
(void)fprintf(stderr, USAGE, progname, progname); |
|||
(void)fputs("Try `file --help' for more information.\n", stderr); |
|||
exit(1); |
|||
} |
|||
|
|||
private void |
|||
help(void) |
|||
{ |
|||
(void)fputs( |
|||
"Usage: file [OPTION...] [FILE...]\n" |
|||
"Determine type of FILEs.\n" |
|||
"\n", stderr); |
|||
#define OPT(shortname, longname, opt, doc) \ |
|||
fprintf(stderr, " -%c, --" longname doc, shortname); |
|||
#define OPT_LONGONLY(longname, opt, doc) \ |
|||
fprintf(stderr, " --" longname doc); |
|||
#include "file_opts.h" |
|||
#undef OPT |
|||
#undef OPT_LONGONLY |
|||
exit(0); |
|||
} |
|||
@ -0,0 +1,392 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* file.h - definitions for file(1) program |
|||
* @(#)$File: file.h,v 1.103 2008/03/01 22:21:49 rrt Exp $ |
|||
*/ |
|||
|
|||
#ifndef __file_h__ |
|||
#define __file_h__ |
|||
|
|||
//#ifdef HAVE_CONFIG_H |
|||
#include "config.h" |
|||
//#endif */ |
|||
|
|||
#include <stdio.h> /* Include that here, to make sure __P gets defined */ |
|||
#include <errno.h> |
|||
#include <fcntl.h> /* For open and flags */ |
|||
#ifdef HAVE_STDINT_H |
|||
#include <stdint.h> |
|||
#endif |
|||
#ifdef HAVE_INTTYPES_H |
|||
#include <inttypes.h> |
|||
#endif |
|||
#include <regex.h> |
|||
#include <sys/types.h> |
|||
/* Do this here and now, because struct stat gets re-defined on solaris */ |
|||
#include <sys/stat.h> |
|||
#include <stdarg.h> |
|||
|
|||
#define ENABLE_CONDITIONALS |
|||
|
|||
#ifndef MAGIC |
|||
#define MAGIC "/etc/magic" |
|||
#endif |
|||
|
|||
#ifdef __EMX__ |
|||
#define PATHSEP ';' |
|||
#else |
|||
#define PATHSEP ':' |
|||
#endif |
|||
|
|||
#define private static |
|||
#ifndef protected |
|||
#define protected |
|||
#endif |
|||
#define public |
|||
|
|||
#ifndef __GNUC_PREREQ__ |
|||
#ifdef __GNUC__ |
|||
#define __GNUC_PREREQ__(x, y) \ |
|||
((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ |
|||
(__GNUC__ > (x))) |
|||
#else |
|||
#define __GNUC_PREREQ__(x, y) 0 |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef MIN |
|||
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) |
|||
#endif |
|||
|
|||
#ifndef MAX |
|||
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) |
|||
#endif |
|||
|
|||
#ifndef HOWMANY |
|||
# define HOWMANY (256 * 1024) /* how much of the file to look at */ |
|||
#endif |
|||
#define MAXMAGIS 8192 /* max entries in any one magic file |
|||
or directory */ |
|||
#define MAXDESC 64 /* max leng of text description/MIME type */ |
|||
#define MAXstring 32 /* max leng of "string" types */ |
|||
|
|||
#define MAGICNO 0xF11E041C |
|||
#define VERSIONNO 5 |
|||
#define FILE_MAGICSIZE (32 * 6) |
|||
|
|||
#define FILE_LOAD 0 |
|||
#define FILE_CHECK 1 |
|||
#define FILE_COMPILE 2 |
|||
|
|||
struct magic { |
|||
/* Word 1 */ |
|||
uint16_t cont_level; /* level of ">" */ |
|||
uint8_t flag; |
|||
#define INDIR 0x01 /* if '(...)' appears */ |
|||
#define OFFADD 0x02 /* if '>&' or '>...(&' appears */ |
|||
#define INDIROFFADD 0x04 /* if '>&(' appears */ |
|||
#define UNSIGNED 0x08 /* comparison is unsigned */ |
|||
#define NOSPACE 0x10 /* suppress space character before output */ |
|||
#define BINTEST 0x20 /* test is for a binary type (set only |
|||
for top-level tests) */ |
|||
#define TEXTTEST 0 /* for passing to file_softmagic */ |
|||
|
|||
uint8_t dummy1; |
|||
|
|||
/* Word 2 */ |
|||
uint8_t reln; /* relation (0=eq, '>'=gt, etc) */ |
|||
uint8_t vallen; /* length of string value, if any */ |
|||
uint8_t type; /* comparison type (FILE_*) */ |
|||
uint8_t in_type; /* type of indirection */ |
|||
#define FILE_INVALID 0 |
|||
#define FILE_BYTE 1 |
|||
#define FILE_SHORT 2 |
|||
#define FILE_DEFAULT 3 |
|||
#define FILE_LONG 4 |
|||
#define FILE_STRING 5 |
|||
#define FILE_DATE 6 |
|||
#define FILE_BESHORT 7 |
|||
#define FILE_BELONG 8 |
|||
#define FILE_BEDATE 9 |
|||
#define FILE_LESHORT 10 |
|||
#define FILE_LELONG 11 |
|||
#define FILE_LEDATE 12 |
|||
#define FILE_PSTRING 13 |
|||
#define FILE_LDATE 14 |
|||
#define FILE_BELDATE 15 |
|||
#define FILE_LELDATE 16 |
|||
#define FILE_REGEX 17 |
|||
#define FILE_BESTRING16 18 |
|||
#define FILE_LESTRING16 19 |
|||
#define FILE_SEARCH 20 |
|||
#define FILE_MEDATE 21 |
|||
#define FILE_MELDATE 22 |
|||
#define FILE_MELONG 23 |
|||
#define FILE_QUAD 24 |
|||
#define FILE_LEQUAD 25 |
|||
#define FILE_BEQUAD 26 |
|||
#define FILE_QDATE 27 |
|||
#define FILE_LEQDATE 28 |
|||
#define FILE_BEQDATE 29 |
|||
#define FILE_QLDATE 30 |
|||
#define FILE_LEQLDATE 31 |
|||
#define FILE_BEQLDATE 32 |
|||
#define FILE_FLOAT 33 |
|||
#define FILE_BEFLOAT 34 |
|||
#define FILE_LEFLOAT 35 |
|||
#define FILE_DOUBLE 36 |
|||
#define FILE_BEDOUBLE 37 |
|||
#define FILE_LEDOUBLE 38 |
|||
#define FILE_NAMES_SIZE 39/* size of array to contain all names */ |
|||
|
|||
#define IS_STRING(t) \ |
|||
((t) == FILE_STRING || \ |
|||
(t) == FILE_PSTRING || \ |
|||
(t) == FILE_BESTRING16 || \ |
|||
(t) == FILE_LESTRING16 || \ |
|||
(t) == FILE_REGEX || \ |
|||
(t) == FILE_SEARCH || \ |
|||
(t) == FILE_DEFAULT) |
|||
|
|||
#define FILE_FMT_NONE 0 |
|||
#define FILE_FMT_NUM 1 /* "cduxXi" */ |
|||
#define FILE_FMT_STR 2 /* "s" */ |
|||
#define FILE_FMT_QUAD 3 /* "ll" */ |
|||
#define FILE_FMT_FLOAT 4 /* "eEfFgG" */ |
|||
#define FILE_FMT_DOUBLE 5 /* "eEfFgG" */ |
|||
|
|||
/* Word 3 */ |
|||
uint8_t in_op; /* operator for indirection */ |
|||
uint8_t mask_op; /* operator for mask */ |
|||
#ifdef ENABLE_CONDITIONALS |
|||
uint8_t cond; /* conditional type */ |
|||
uint8_t dummy2; |
|||
#else |
|||
uint8_t dummy2; |
|||
uint8_t dummy3; |
|||
#endif |
|||
|
|||
#define FILE_OPS "&|^+-*/%" |
|||
#define FILE_OPAND 0 |
|||
#define FILE_OPOR 1 |
|||
#define FILE_OPXOR 2 |
|||
#define FILE_OPADD 3 |
|||
#define FILE_OPMINUS 4 |
|||
#define FILE_OPMULTIPLY 5 |
|||
#define FILE_OPDIVIDE 6 |
|||
#define FILE_OPMODULO 7 |
|||
#define FILE_OPS_MASK 0x07 /* mask for above ops */ |
|||
#define FILE_UNUSED_1 0x08 |
|||
#define FILE_UNUSED_2 0x10 |
|||
#define FILE_UNUSED_3 0x20 |
|||
#define FILE_OPINVERSE 0x40 |
|||
#define FILE_OPINDIRECT 0x80 |
|||
|
|||
#ifdef ENABLE_CONDITIONALS |
|||
#define COND_NONE 0 |
|||
#define COND_IF 1 |
|||
#define COND_ELIF 2 |
|||
#define COND_ELSE 3 |
|||
#endif /* ENABLE_CONDITIONALS */ |
|||
|
|||
/* Word 4 */ |
|||
uint32_t offset; /* offset to magic number */ |
|||
/* Word 5 */ |
|||
int32_t in_offset; /* offset from indirection */ |
|||
/* Word 6 */ |
|||
uint32_t lineno; /* line number in magic file */ |
|||
/* Word 7,8 */ |
|||
union { |
|||
uint64_t _mask; /* for use with numeric and date types */ |
|||
struct { |
|||
uint32_t _count; /* repeat/line count */ |
|||
uint32_t _flags; /* modifier flags */ |
|||
} _s; /* for use with string types */ |
|||
} _u; |
|||
#define num_mask _u._mask |
|||
#define str_range _u._s._count |
|||
#define str_flags _u._s._flags |
|||
|
|||
/* Words 9-16 */ |
|||
union VALUETYPE { |
|||
uint8_t b; |
|||
uint16_t h; |
|||
uint32_t l; |
|||
uint64_t q; |
|||
uint8_t hs[2]; /* 2 bytes of a fixed-endian "short" */ |
|||
uint8_t hl[4]; /* 4 bytes of a fixed-endian "long" */ |
|||
uint8_t hq[8]; /* 8 bytes of a fixed-endian "quad" */ |
|||
char s[MAXstring]; /* the search string or regex pattern */ |
|||
float f; |
|||
double d; |
|||
} value; /* either number or string */ |
|||
/* Words 17..31 */ |
|||
char desc[MAXDESC]; /* description */ |
|||
/* Words 32..47 */ |
|||
char mimetype[MAXDESC]; /* MIME type */ |
|||
}; |
|||
|
|||
#define BIT(A) (1 << (A)) |
|||
#define STRING_COMPACT_BLANK BIT(0) |
|||
#define STRING_COMPACT_OPTIONAL_BLANK BIT(1) |
|||
#define STRING_IGNORE_LOWERCASE BIT(2) |
|||
#define STRING_IGNORE_UPPERCASE BIT(3) |
|||
#define REGEX_OFFSET_START BIT(4) |
|||
#define CHAR_COMPACT_BLANK 'B' |
|||
#define CHAR_COMPACT_OPTIONAL_BLANK 'b' |
|||
#define CHAR_IGNORE_LOWERCASE 'c' |
|||
#define CHAR_IGNORE_UPPERCASE 'C' |
|||
#define CHAR_REGEX_OFFSET_START 's' |
|||
#define STRING_IGNORE_CASE (STRING_IGNORE_LOWERCASE|STRING_IGNORE_UPPERCASE) |
|||
#define STRING_DEFAULT_RANGE 100 |
|||
|
|||
|
|||
/* list of magic entries */ |
|||
struct mlist { |
|||
struct magic *magic; /* array of magic entries */ |
|||
uint32_t nmagic; /* number of entries in array */ |
|||
int mapped; /* allocation type: 0 => apprentice_file |
|||
* 1 => apprentice_map + malloc |
|||
* 2 => apprentice_map + mmap */ |
|||
struct mlist *next, *prev; |
|||
}; |
|||
|
|||
struct magic_set { |
|||
struct mlist *mlist; |
|||
struct cont { |
|||
size_t len; |
|||
struct level_info { |
|||
int32_t off; |
|||
int got_match; |
|||
#ifdef ENABLE_CONDITIONALS |
|||
int last_match; |
|||
int last_cond; /* used for error checking by parse() */ |
|||
#endif |
|||
} *li; |
|||
} c; |
|||
struct out { |
|||
char *buf; /* Accumulation buffer */ |
|||
char *pbuf; /* Printable buffer */ |
|||
} o; |
|||
uint32_t offset; |
|||
int error; |
|||
int flags; |
|||
int haderr; |
|||
const char *file; |
|||
size_t line; /* current magic line number */ |
|||
|
|||
/* data for searches */ |
|||
struct { |
|||
const char *s; /* start of search in original source */ |
|||
size_t s_len; /* length of search region */ |
|||
size_t offset; /* starting offset in source: XXX - should this be off_t? */ |
|||
size_t rm_len; /* match length */ |
|||
} search; |
|||
|
|||
/* FIXME: Make the string dynamically allocated so that e.g. |
|||
strings matched in files can be longer than MAXstring */ |
|||
union VALUETYPE ms_value; /* either number or string */ |
|||
}; |
|||
|
|||
/* Type for Unicode characters */ |
|||
typedef unsigned long unichar; |
|||
|
|||
struct stat; |
|||
protected const char *file_fmttime(uint32_t, int); |
|||
protected int file_buffer(struct magic_set *, int, const char *, const void *, |
|||
size_t); |
|||
protected int file_fsmagic(struct magic_set *, const char *, struct stat *); |
|||
protected int file_pipe2file(struct magic_set *, int, const void *, size_t); |
|||
protected int file_printf(struct magic_set *, const char *, ...); |
|||
protected int file_reset(struct magic_set *); |
|||
protected int file_tryelf(struct magic_set *, int, const unsigned char *, |
|||
size_t); |
|||
protected int file_zmagic(struct magic_set *, int, const char *, |
|||
const unsigned char *, size_t); |
|||
protected int file_ascmagic(struct magic_set *, const unsigned char *, size_t); |
|||
protected int file_is_tar(struct magic_set *, const unsigned char *, size_t); |
|||
protected int file_softmagic(struct magic_set *, const unsigned char *, size_t, int); |
|||
protected struct mlist *file_apprentice(struct magic_set *, const char *, int); |
|||
protected uint64_t file_signextend(struct magic_set *, struct magic *, |
|||
uint64_t); |
|||
protected void file_delmagic(struct magic *, int type, size_t entries); |
|||
protected void file_badread(struct magic_set *); |
|||
protected void file_badseek(struct magic_set *); |
|||
protected void file_oomem(struct magic_set *, size_t); |
|||
protected void file_error(struct magic_set *, int, const char *, ...); |
|||
protected void file_magerror(struct magic_set *, const char *, ...); |
|||
protected void file_magwarn(struct magic_set *, const char *, ...); |
|||
protected void file_mdump(struct magic *); |
|||
protected void file_showstr(FILE *, const char *, size_t); |
|||
protected size_t file_mbswidth(const char *); |
|||
protected const char *file_getbuffer(struct magic_set *); |
|||
protected ssize_t sread(int, void *, size_t, int); |
|||
protected int file_check_mem(struct magic_set *, unsigned int); |
|||
protected int file_looks_utf8(const unsigned char *, size_t, unichar *, size_t *); |
|||
|
|||
#ifndef COMPILE_ONLY |
|||
extern const char *file_names[]; |
|||
extern const size_t file_nnames; |
|||
#endif |
|||
|
|||
#ifndef HAVE_STRERROR |
|||
extern int sys_nerr; |
|||
extern char *sys_errlist[]; |
|||
#define strerror(e) \ |
|||
(((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error") |
|||
#endif |
|||
|
|||
#ifndef HAVE_STRTOUL |
|||
#define strtoul(a, b, c) strtol(a, b, c) |
|||
#endif |
|||
|
|||
#ifndef HAVE_VASPRINTF |
|||
int vasprintf(char **ptr, const char *format_string, va_list vargs); |
|||
#endif |
|||
#ifndef HAVE_ASPRINTF |
|||
int asprintf(char **ptr, const char *format_string, ...); |
|||
#endif |
|||
|
|||
#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK) |
|||
#define QUICK |
|||
#endif |
|||
|
|||
#ifndef O_BINARY |
|||
#define O_BINARY 0 |
|||
#endif |
|||
|
|||
#ifdef __GNUC__ |
|||
static const char *rcsid(const char *) __attribute__((__used__)); |
|||
#endif |
|||
#define FILE_RCSID(id) \ |
|||
static const char *rcsid(const char *p) { \ |
|||
return rcsid(p = id); \ |
|||
} |
|||
|
|||
#endif /* __file_h__ */ |
|||
@ -0,0 +1,48 @@ |
|||
/* |
|||
* Table of command-line options |
|||
* |
|||
* The first column specifies the short name, if any, or 0 if none. |
|||
* The second column specifies the long name. |
|||
* The third column specifies whether it takes a parameter. |
|||
* The fourth column is the documentation. |
|||
* |
|||
* N.B. The long options' order must correspond to the code in file.c, |
|||
* and OPTSTRING must be kept up-to-date with the short options. |
|||
* Pay particular attention to the numbers of long-only options in the |
|||
* switch statement! |
|||
*/ |
|||
|
|||
OPT_LONGONLY("help", 0, " display this help and exit\n") |
|||
OPT('v', "version", 0, " output version information and exit\n") |
|||
OPT('m', "magic-file", 1, " LIST use LIST as a colon-separated list of magic\n" |
|||
" number files\n") |
|||
OPT('z', "uncompress", 0, " try to look inside compressed files\n") |
|||
OPT('b', "brief", 0, " do not prepend filenames to output lines\n") |
|||
OPT('c', "checking-printout", 0, " print the parsed form of the magic file, use in\n" |
|||
" conjunction with -m to debug a new magic file\n" |
|||
" before installing it\n") |
|||
OPT('e', "exclude", 1, " TEST exclude TEST from the list of test to be\n" |
|||
" performed for file. Valid tests are:\n" |
|||
" ascii, apptype, compress, elf, soft, tar, tokens, troff\n") |
|||
OPT('f', "files-from", 1, " FILE read the filenames to be examined from FILE\n") |
|||
OPT('F', "separator", 1, " STRING use string as separator instead of `:'\n") |
|||
OPT('i', "mime", 0, " output MIME type strings (--mime-type and\n" |
|||
" --mime-encoding)\n") |
|||
OPT_LONGONLY("mime-type", 0, " output the MIME type\n") |
|||
OPT_LONGONLY("mime-encoding", 0, " output the MIME encoding\n") |
|||
OPT('k', "keep-going", 0, " don't stop at the first match\n") |
|||
#ifdef S_IFLNK |
|||
OPT('L', "dereference", 0, " follow symlinks (default)\n") |
|||
OPT('h', "no-dereference", 0, " don't follow symlinks\n") |
|||
#endif |
|||
OPT('n', "no-buffer", 0, " do not buffer output\n") |
|||
OPT('N', "no-pad", 0, " do not pad output\n") |
|||
OPT('0', "print0", 0, " terminate filenames with ASCII NUL\n") |
|||
#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) |
|||
OPT('p', "preserve-date", 0, " preserve access times on files\n") |
|||
#endif |
|||
OPT('r', "raw", 0, " don't translate unprintable chars to \\ooo\n") |
|||
OPT('s', "special-files", 0, " treat special (block/char devices) files as\n" |
|||
" ordinary ones\n") |
|||
OPT('C', "compile", 0, " compile file specified by -m\n") |
|||
OPT('d', "debug", 0, " print debugging messages\n") |
|||
@ -0,0 +1,312 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* fsmagic - magic based on filesystem info - directory, special files, etc. |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
#include "magic.h" |
|||
#include <string.h> |
|||
#ifdef HAVE_UNISTD_H |
|||
#include <unistd.h> |
|||
#endif |
|||
#include <stdlib.h> |
|||
#include <sys/stat.h> |
|||
/* Since major is a function on SVR4, we cannot use `ifndef major'. */ |
|||
#ifdef MAJOR_IN_MKDEV |
|||
# include <sys/mkdev.h> |
|||
# define HAVE_MAJOR |
|||
#endif |
|||
#ifdef MAJOR_IN_SYSMACROS |
|||
# include <sys/sysmacros.h> |
|||
# define HAVE_MAJOR |
|||
#endif |
|||
#ifdef major /* Might be defined in sys/types.h. */ |
|||
# define HAVE_MAJOR |
|||
#endif |
|||
|
|||
#ifndef HAVE_MAJOR |
|||
# define major(dev) (((dev) >> 8) & 0xff) |
|||
# define minor(dev) ((dev) & 0xff) |
|||
#endif |
|||
#undef HAVE_MAJOR |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: fsmagic.c,v 1.50 2008/02/12 17:22:54 rrt Exp $") |
|||
#endif /* lint */ |
|||
|
|||
private int |
|||
bad_link(struct magic_set *ms, int err, char *buf) |
|||
{ |
|||
char *errfmt; |
|||
if (err == ELOOP) |
|||
errfmt = "symbolic link in a loop"; |
|||
else |
|||
errfmt = "broken symbolic link to `%s'"; |
|||
if (ms->flags & MAGIC_ERROR) { |
|||
file_error(ms, err, errfmt, buf); |
|||
return -1; |
|||
} |
|||
if (file_printf(ms, errfmt, buf) == -1) |
|||
return -1; |
|||
return 1; |
|||
} |
|||
|
|||
protected int |
|||
file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) |
|||
{ |
|||
int ret = 0; |
|||
int mime = ms->flags & MAGIC_MIME; |
|||
#ifdef S_IFLNK |
|||
char buf[BUFSIZ+4]; |
|||
int nch; |
|||
struct stat tstatbuf; |
|||
#endif |
|||
|
|||
if (fn == NULL) |
|||
return 0; |
|||
|
|||
/* |
|||
* Fstat is cheaper but fails for files you don't have read perms on. |
|||
* On 4.2BSD and similar systems, use lstat() to identify symlinks. |
|||
*/ |
|||
#ifdef S_IFLNK |
|||
if ((ms->flags & MAGIC_SYMLINK) == 0) |
|||
ret = lstat(fn, sb); |
|||
else |
|||
#endif |
|||
ret = stat(fn, sb); /* don't merge into if; see "ret =" above */ |
|||
|
|||
if (ret) { |
|||
if (ms->flags & MAGIC_ERROR) { |
|||
file_error(ms, errno, "cannot stat `%s'", fn); |
|||
return -1; |
|||
} |
|||
if (file_printf(ms, "cannot open `%s' (%s)", |
|||
fn, strerror(errno)) == -1) |
|||
return -1; |
|||
return 1; |
|||
} |
|||
|
|||
if (mime) { |
|||
if ((sb->st_mode & S_IFMT) != S_IFREG) { |
|||
if ((mime & MAGIC_MIME_TYPE) && |
|||
file_printf(ms, "application/x-not-regular-file") |
|||
== -1) |
|||
return -1; |
|||
return 1; |
|||
} |
|||
} |
|||
else { |
|||
#ifdef S_ISUID |
|||
if (sb->st_mode & S_ISUID) |
|||
if (file_printf(ms, "setuid ") == -1) |
|||
return -1; |
|||
#endif |
|||
#ifdef S_ISGID |
|||
if (sb->st_mode & S_ISGID) |
|||
if (file_printf(ms, "setgid ") == -1) |
|||
return -1; |
|||
#endif |
|||
#ifdef S_ISVTX |
|||
if (sb->st_mode & S_ISVTX) |
|||
if (file_printf(ms, "sticky ") == -1) |
|||
return -1; |
|||
#endif |
|||
} |
|||
|
|||
switch (sb->st_mode & S_IFMT) { |
|||
case S_IFDIR: |
|||
if (file_printf(ms, "directory") == -1) |
|||
return -1; |
|||
return 1; |
|||
#ifdef S_IFCHR |
|||
case S_IFCHR: |
|||
/* |
|||
* If -s has been specified, treat character special files |
|||
* like ordinary files. Otherwise, just report that they |
|||
* are block special files and go on to the next file. |
|||
*/ |
|||
if ((ms->flags & MAGIC_DEVICES) != 0) |
|||
break; |
|||
#ifdef HAVE_STAT_ST_RDEV |
|||
# ifdef dv_unit |
|||
if (file_printf(ms, "character special (%d/%d/%d)", |
|||
major(sb->st_rdev), dv_unit(sb->st_rdev), |
|||
dv_subunit(sb->st_rdev)) == -1) |
|||
return -1; |
|||
# else |
|||
if (file_printf(ms, "character special (%ld/%ld)", |
|||
(long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1) |
|||
return -1; |
|||
# endif |
|||
#else |
|||
if (file_printf(ms, "character special") == -1) |
|||
return -1; |
|||
#endif |
|||
return 1; |
|||
#endif |
|||
#ifdef S_IFBLK |
|||
case S_IFBLK: |
|||
/* |
|||
* If -s has been specified, treat block special files |
|||
* like ordinary files. Otherwise, just report that they |
|||
* are block special files and go on to the next file. |
|||
*/ |
|||
if ((ms->flags & MAGIC_DEVICES) != 0) |
|||
break; |
|||
#ifdef HAVE_STAT_ST_RDEV |
|||
# ifdef dv_unit |
|||
if (file_printf(ms, "block special (%d/%d/%d)", |
|||
major(sb->st_rdev), dv_unit(sb->st_rdev), |
|||
dv_subunit(sb->st_rdev)) == -1) |
|||
return -1; |
|||
# else |
|||
if (file_printf(ms, "block special (%ld/%ld)", |
|||
(long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1) |
|||
return -1; |
|||
# endif |
|||
#else |
|||
if (file_printf(ms, "block special") == -1) |
|||
return -1; |
|||
#endif |
|||
return 1; |
|||
#endif |
|||
/* TODO add code to handle V7 MUX and Blit MUX files */ |
|||
#ifdef S_IFIFO |
|||
case S_IFIFO: |
|||
if((ms->flags & MAGIC_DEVICES) != 0) |
|||
break; |
|||
if (file_printf(ms, "fifo (named pipe)") == -1) |
|||
return -1; |
|||
return 1; |
|||
#endif |
|||
#ifdef S_IFDOOR |
|||
case S_IFDOOR: |
|||
if (file_printf(ms, "door") == -1) |
|||
return -1; |
|||
return 1; |
|||
#endif |
|||
#ifdef S_IFLNK |
|||
case S_IFLNK: |
|||
if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) { |
|||
if (ms->flags & MAGIC_ERROR) { |
|||
file_error(ms, errno, "unreadable symlink `%s'", |
|||
fn); |
|||
return -1; |
|||
} |
|||
if (file_printf(ms, |
|||
"unreadable symlink `%s' (%s)", fn, |
|||
strerror(errno)) == -1) |
|||
return -1; |
|||
return 1; |
|||
} |
|||
buf[nch] = '\0'; /* readlink(2) does not do this */ |
|||
|
|||
/* If broken symlink, say so and quit early. */ |
|||
if (*buf == '/') { |
|||
if (stat(buf, &tstatbuf) < 0) |
|||
return bad_link(ms, errno, buf); |
|||
} else { |
|||
char *tmp; |
|||
char buf2[BUFSIZ+BUFSIZ+4]; |
|||
|
|||
if ((tmp = strrchr(fn, '/')) == NULL) { |
|||
tmp = buf; /* in current directory anyway */ |
|||
} else { |
|||
if (tmp - fn + 1 > BUFSIZ) { |
|||
if (ms->flags & MAGIC_ERROR) { |
|||
file_error(ms, 0, |
|||
"path too long: `%s'", buf); |
|||
return -1; |
|||
} |
|||
if (file_printf(ms, |
|||
"path too long: `%s'", fn) == -1) |
|||
return -1; |
|||
return 1; |
|||
} |
|||
(void)strcpy(buf2, fn); /* take dir part */ |
|||
buf2[tmp - fn + 1] = '\0'; |
|||
(void)strcat(buf2, buf); /* plus (rel) link */ |
|||
tmp = buf2; |
|||
} |
|||
if (stat(tmp, &tstatbuf) < 0) |
|||
return bad_link(ms, errno, buf); |
|||
} |
|||
|
|||
/* Otherwise, handle it. */ |
|||
if ((ms->flags & MAGIC_SYMLINK) != 0) { |
|||
const char *p; |
|||
ms->flags &= MAGIC_SYMLINK; |
|||
p = magic_file(ms, buf); |
|||
ms->flags |= MAGIC_SYMLINK; |
|||
return p != NULL ? 1 : -1; |
|||
} else { /* just print what it points to */ |
|||
if (file_printf(ms, "symbolic link to `%s'", |
|||
buf) == -1) |
|||
return -1; |
|||
} |
|||
return 1; |
|||
#endif |
|||
#ifdef S_IFSOCK |
|||
#ifndef __COHERENT__ |
|||
case S_IFSOCK: |
|||
if (file_printf(ms, "socket") == -1) |
|||
return -1; |
|||
return 1; |
|||
#endif |
|||
#endif |
|||
case S_IFREG: |
|||
break; |
|||
default: |
|||
file_error(ms, 0, "invalid mode 0%o", sb->st_mode); |
|||
return -1; |
|||
/*NOTREACHED*/ |
|||
} |
|||
|
|||
/* |
|||
* regular file, check next possibility |
|||
* |
|||
* If stat() tells us the file has zero length, report here that |
|||
* the file is empty, so we can skip all the work of opening and |
|||
* reading the file. |
|||
* But if the -s option has been given, we skip this optimization, |
|||
* since on some systems, stat() reports zero size for raw disk |
|||
* partitions. (If the block special device really has zero length, |
|||
* the fact that it is empty will be detected and reported correctly |
|||
* when we read the file.) |
|||
*/ |
|||
if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) { |
|||
if ((!mime || (mime & MAGIC_MIME_TYPE)) && |
|||
file_printf(ms, mime ? "application/x-empty" : |
|||
"empty") == -1) |
|||
return -1; |
|||
return 1; |
|||
} |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,482 @@ |
|||
/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */ |
|||
|
|||
/*- |
|||
* Copyright (c) 2000 The NetBSD Foundation, Inc. |
|||
* All rights reserved. |
|||
* |
|||
* This code is derived from software contributed to The NetBSD Foundation |
|||
* by Dieter Baron and Thomas Klausner. |
|||
* |
|||
* 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, 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include <err.h> |
|||
#include <errno.h> |
|||
#include <getopt.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
#define REPLACE_GETOPT |
|||
|
|||
#define _DIAGASSERT assert |
|||
|
|||
#ifdef REPLACE_GETOPT |
|||
#ifdef __weak_alias |
|||
__weak_alias(getopt,_getopt) |
|||
#endif |
|||
int opterr = 1; /* if error message should be printed */ |
|||
int optind = 1; /* index into parent argv vector */ |
|||
int optopt = '?'; /* character checked for validity */ |
|||
int optreset; /* reset getopt */ |
|||
char *optarg; /* argument associated with option */ |
|||
#elif HAVE_NBTOOL_CONFIG_H && !HAVE_DECL_OPTRESET |
|||
static int optreset; |
|||
#endif |
|||
|
|||
#ifdef __weak_alias |
|||
__weak_alias(getopt_long,_getopt_long) |
|||
#endif |
|||
|
|||
#define IGNORE_FIRST (*options == '-' || *options == '+') |
|||
#define PRINT_ERROR ((opterr) && ((*options != ':') \ |
|||
|| (IGNORE_FIRST && options[1] != ':'))) |
|||
#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) |
|||
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) |
|||
/* XXX: GNU ignores PC if *options == '-' */ |
|||
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') |
|||
|
|||
/* return values */ |
|||
#define BADCH (int)'?' |
|||
#define BADARG ((IGNORE_FIRST && options[1] == ':') \ |
|||
|| (*options == ':') ? (int)':' : (int)'?') |
|||
#define INORDER (int)1 |
|||
|
|||
#define EMSG "" |
|||
|
|||
static int getopt_internal __P((int, char **, const char *)); |
|||
static int gcd __P((int, int)); |
|||
static void permute_args __P((int, int, int, char **)); |
|||
|
|||
static const char *place = EMSG; /* option letter processing */ |
|||
|
|||
/* XXX: set optreset to 1 rather than these two */ |
|||
static int nonopt_start = -1; /* first non option argument (for permute) */ |
|||
static int nonopt_end = -1; /* first option after non options (for permute) */ |
|||
|
|||
/* Error messages */ |
|||
static const char recargchar[] = "option requires an argument -- %c"; |
|||
static const char recargstring[] = "option requires an argument -- %s"; |
|||
static const char ambig[] = "ambiguous option -- %.*s"; |
|||
static const char noarg[] = "option doesn't take an argument -- %.*s"; |
|||
static const char illoptchar[] = "unknown option -- %c"; |
|||
static const char illoptstring[] = "unknown option -- %s"; |
|||
|
|||
|
|||
/* |
|||
* Compute the greatest common divisor of a and b. |
|||
*/ |
|||
static int |
|||
gcd(a, b) |
|||
int a; |
|||
int b; |
|||
{ |
|||
int c; |
|||
|
|||
c = a % b; |
|||
while (c != 0) { |
|||
a = b; |
|||
b = c; |
|||
c = a % b; |
|||
} |
|||
|
|||
return b; |
|||
} |
|||
|
|||
/* |
|||
* Exchange the block from nonopt_start to nonopt_end with the block |
|||
* from nonopt_end to opt_end (keeping the same order of arguments |
|||
* in each block). |
|||
*/ |
|||
static void |
|||
permute_args(panonopt_start, panonopt_end, opt_end, nargv) |
|||
int panonopt_start; |
|||
int panonopt_end; |
|||
int opt_end; |
|||
char **nargv; |
|||
{ |
|||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
|||
char *swap; |
|||
|
|||
_DIAGASSERT(nargv != NULL); |
|||
|
|||
/* |
|||
* compute lengths of blocks and number and size of cycles |
|||
*/ |
|||
nnonopts = panonopt_end - panonopt_start; |
|||
nopts = opt_end - panonopt_end; |
|||
ncycle = gcd(nnonopts, nopts); |
|||
cyclelen = (opt_end - panonopt_start) / ncycle; |
|||
|
|||
for (i = 0; i < ncycle; i++) { |
|||
cstart = panonopt_end+i; |
|||
pos = cstart; |
|||
for (j = 0; j < cyclelen; j++) { |
|||
if (pos >= panonopt_end) |
|||
pos -= nnonopts; |
|||
else |
|||
pos += nopts; |
|||
swap = nargv[pos]; |
|||
nargv[pos] = nargv[cstart]; |
|||
nargv[cstart] = swap; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* |
|||
* getopt_internal -- |
|||
* Parse argc/argv argument vector. Called by user level routines. |
|||
* Returns -2 if -- is found (can be long option or end of options marker). |
|||
*/ |
|||
static int |
|||
getopt_internal(nargc, nargv, options) |
|||
int nargc; |
|||
char **nargv; |
|||
const char *options; |
|||
{ |
|||
char *oli; /* option letter list index */ |
|||
int optchar; |
|||
|
|||
_DIAGASSERT(nargv != NULL); |
|||
_DIAGASSERT(options != NULL); |
|||
|
|||
optarg = NULL; |
|||
|
|||
/* |
|||
* XXX Some programs (like rsyncd) expect to be able to |
|||
* XXX re-initialize optind to 0 and have getopt_long(3) |
|||
* XXX properly function again. Work around this braindamage. |
|||
*/ |
|||
if (optind == 0) |
|||
optind = 1; |
|||
|
|||
if (optreset) |
|||
nonopt_start = nonopt_end = -1; |
|||
start: |
|||
if (optreset || !*place) { /* update scanning pointer */ |
|||
optreset = 0; |
|||
if (optind >= nargc) { /* end of argument vector */ |
|||
place = EMSG; |
|||
if (nonopt_end != -1) { |
|||
/* do permutation, if we have to */ |
|||
permute_args(nonopt_start, nonopt_end, |
|||
optind, nargv); |
|||
optind -= nonopt_end - nonopt_start; |
|||
} |
|||
else if (nonopt_start != -1) { |
|||
/* |
|||
* If we skipped non-options, set optind |
|||
* to the first of them. |
|||
*/ |
|||
optind = nonopt_start; |
|||
} |
|||
nonopt_start = nonopt_end = -1; |
|||
return -1; |
|||
} |
|||
if ((*(place = nargv[optind]) != '-') |
|||
|| (place[1] == '\0')) { /* found non-option */ |
|||
place = EMSG; |
|||
if (IN_ORDER) { |
|||
/* |
|||
* GNU extension: |
|||
* return non-option as argument to option 1 |
|||
*/ |
|||
optarg = nargv[optind++]; |
|||
return INORDER; |
|||
} |
|||
if (!PERMUTE) { |
|||
/* |
|||
* if no permutation wanted, stop parsing |
|||
* at first non-option |
|||
*/ |
|||
return -1; |
|||
} |
|||
/* do permutation */ |
|||
if (nonopt_start == -1) |
|||
nonopt_start = optind; |
|||
else if (nonopt_end != -1) { |
|||
permute_args(nonopt_start, nonopt_end, |
|||
optind, nargv); |
|||
nonopt_start = optind - |
|||
(nonopt_end - nonopt_start); |
|||
nonopt_end = -1; |
|||
} |
|||
optind++; |
|||
/* process next argument */ |
|||
goto start; |
|||
} |
|||
if (nonopt_start != -1 && nonopt_end == -1) |
|||
nonopt_end = optind; |
|||
if (place[1] && *++place == '-') { /* found "--" */ |
|||
place++; |
|||
return -2; |
|||
} |
|||
} |
|||
if ((optchar = (int)*place++) == (int)':' || |
|||
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
|||
/* option letter unknown or ':' */ |
|||
if (!*place) |
|||
++optind; |
|||
if (PRINT_ERROR) |
|||
warnx(illoptchar, optchar); |
|||
optopt = optchar; |
|||
return BADCH; |
|||
} |
|||
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ |
|||
/* XXX: what if no long options provided (called by getopt)? */ |
|||
if (*place) |
|||
return -2; |
|||
|
|||
if (++optind >= nargc) { /* no arg */ |
|||
place = EMSG; |
|||
if (PRINT_ERROR) |
|||
warnx(recargchar, optchar); |
|||
optopt = optchar; |
|||
return BADARG; |
|||
} else /* white space */ |
|||
place = nargv[optind]; |
|||
/* |
|||
* Handle -W arg the same as --arg (which causes getopt to |
|||
* stop parsing). |
|||
*/ |
|||
return -2; |
|||
} |
|||
if (*++oli != ':') { /* doesn't take argument */ |
|||
if (!*place) |
|||
++optind; |
|||
} else { /* takes (optional) argument */ |
|||
optarg = NULL; |
|||
if (*place) /* no white space */ |
|||
optarg = (char *)place; |
|||
/* XXX: disable test for :: if PC? (GNU doesn't) */ |
|||
else if (oli[1] != ':') { /* arg not optional */ |
|||
if (++optind >= nargc) { /* no arg */ |
|||
place = EMSG; |
|||
if (PRINT_ERROR) |
|||
warnx(recargchar, optchar); |
|||
optopt = optchar; |
|||
return BADARG; |
|||
} else |
|||
optarg = nargv[optind]; |
|||
} |
|||
place = EMSG; |
|||
++optind; |
|||
} |
|||
/* dump back option letter */ |
|||
return optchar; |
|||
} |
|||
|
|||
#ifdef REPLACE_GETOPT |
|||
/* |
|||
* getopt -- |
|||
* Parse argc/argv argument vector. |
|||
* |
|||
* [eventually this will replace the real getopt] |
|||
*/ |
|||
int |
|||
getopt(nargc, nargv, options) |
|||
int nargc; |
|||
char * const *nargv; |
|||
const char *options; |
|||
{ |
|||
int retval; |
|||
|
|||
_DIAGASSERT(nargv != NULL); |
|||
_DIAGASSERT(options != NULL); |
|||
|
|||
retval = getopt_internal(nargc, (char **)nargv, options); |
|||
if (retval == -2) { |
|||
++optind; |
|||
/* |
|||
* We found an option (--), so if we skipped non-options, |
|||
* we have to permute. |
|||
*/ |
|||
if (nonopt_end != -1) { |
|||
permute_args(nonopt_start, nonopt_end, optind, |
|||
(char **)nargv); |
|||
optind -= nonopt_end - nonopt_start; |
|||
} |
|||
nonopt_start = nonopt_end = -1; |
|||
retval = -1; |
|||
} |
|||
return retval; |
|||
} |
|||
#endif |
|||
|
|||
/* |
|||
* getopt_long -- |
|||
* Parse argc/argv argument vector. |
|||
*/ |
|||
int |
|||
getopt_long(nargc, nargv, options, long_options, idx) |
|||
int nargc; |
|||
char * const *nargv; |
|||
const char *options; |
|||
const struct option *long_options; |
|||
int *idx; |
|||
{ |
|||
int retval; |
|||
|
|||
#define IDENTICAL_INTERPRETATION(_x, _y) \ |
|||
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ |
|||
long_options[(_x)].flag == long_options[(_y)].flag && \ |
|||
long_options[(_x)].val == long_options[(_y)].val) |
|||
|
|||
_DIAGASSERT(nargv != NULL); |
|||
_DIAGASSERT(options != NULL); |
|||
_DIAGASSERT(long_options != NULL); |
|||
/* idx may be NULL */ |
|||
|
|||
retval = getopt_internal(nargc, (char **)nargv, options); |
|||
if (retval == -2) { |
|||
char *current_argv, *has_equal; |
|||
size_t current_argv_len; |
|||
int i, ambiguous, match; |
|||
|
|||
current_argv = (char *)place; |
|||
match = -1; |
|||
ambiguous = 0; |
|||
|
|||
optind++; |
|||
place = EMSG; |
|||
|
|||
if (*current_argv == '\0') { /* found "--" */ |
|||
/* |
|||
* We found an option (--), so if we skipped |
|||
* non-options, we have to permute. |
|||
*/ |
|||
if (nonopt_end != -1) { |
|||
permute_args(nonopt_start, nonopt_end, |
|||
optind, (char **)nargv); |
|||
optind -= nonopt_end - nonopt_start; |
|||
} |
|||
nonopt_start = nonopt_end = -1; |
|||
return -1; |
|||
} |
|||
if ((has_equal = strchr(current_argv, '=')) != NULL) { |
|||
/* argument found (--option=arg) */ |
|||
current_argv_len = has_equal - current_argv; |
|||
has_equal++; |
|||
} else |
|||
current_argv_len = strlen(current_argv); |
|||
|
|||
for (i = 0; long_options[i].name; i++) { |
|||
/* find matching long option */ |
|||
if (strncmp(current_argv, long_options[i].name, |
|||
current_argv_len)) |
|||
continue; |
|||
|
|||
if (strlen(long_options[i].name) == |
|||
(unsigned)current_argv_len) { |
|||
/* exact match */ |
|||
match = i; |
|||
ambiguous = 0; |
|||
break; |
|||
} |
|||
if (match == -1) /* partial match */ |
|||
match = i; |
|||
else if (!IDENTICAL_INTERPRETATION(i, match)) |
|||
ambiguous = 1; |
|||
} |
|||
if (ambiguous) { |
|||
/* ambiguous abbreviation */ |
|||
if (PRINT_ERROR) |
|||
warnx(ambig, (int)current_argv_len, |
|||
current_argv); |
|||
optopt = 0; |
|||
return BADCH; |
|||
} |
|||
if (match != -1) { /* option found */ |
|||
if (long_options[match].has_arg == no_argument |
|||
&& has_equal) { |
|||
if (PRINT_ERROR) |
|||
warnx(noarg, (int)current_argv_len, |
|||
current_argv); |
|||
/* |
|||
* XXX: GNU sets optopt to val regardless of |
|||
* flag |
|||
*/ |
|||
if (long_options[match].flag == NULL) |
|||
optopt = long_options[match].val; |
|||
else |
|||
optopt = 0; |
|||
return BADARG; |
|||
} |
|||
if (long_options[match].has_arg == required_argument || |
|||
long_options[match].has_arg == optional_argument) { |
|||
if (has_equal) |
|||
optarg = has_equal; |
|||
else if (long_options[match].has_arg == |
|||
required_argument) { |
|||
/* |
|||
* optional argument doesn't use |
|||
* next nargv |
|||
*/ |
|||
optarg = nargv[optind++]; |
|||
} |
|||
} |
|||
if ((long_options[match].has_arg == required_argument) |
|||
&& (optarg == NULL)) { |
|||
/* |
|||
* Missing argument; leading ':' |
|||
* indicates no error should be generated |
|||
*/ |
|||
if (PRINT_ERROR) |
|||
warnx(recargstring, current_argv); |
|||
/* |
|||
* XXX: GNU sets optopt to val regardless |
|||
* of flag |
|||
*/ |
|||
if (long_options[match].flag == NULL) |
|||
optopt = long_options[match].val; |
|||
else |
|||
optopt = 0; |
|||
--optind; |
|||
return BADARG; |
|||
} |
|||
} else { /* unknown option */ |
|||
if (PRINT_ERROR) |
|||
warnx(illoptstring, current_argv); |
|||
optopt = 0; |
|||
return BADCH; |
|||
} |
|||
if (long_options[match].flag) { |
|||
*long_options[match].flag = long_options[match].val; |
|||
retval = 0; |
|||
} else |
|||
retval = long_options[match].val; |
|||
if (idx) |
|||
*idx = match; |
|||
} |
|||
return retval; |
|||
#undef IDENTICAL_INTERPRETATION |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* is_tar() -- figure out whether file is a tar archive. |
|||
* |
|||
* Stolen (by the author!) from the public domain tar program: |
|||
* Public Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu). |
|||
* |
|||
* @(#)list.c 1.18 9/23/86 Public Domain - gnu |
|||
* |
|||
* Comments changed and some code/comments reformatted |
|||
* for file command by Ian Darwin. |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
#include "magic.h" |
|||
#include <string.h> |
|||
#include <ctype.h> |
|||
#include <sys/types.h> |
|||
#include "tar.h" |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: is_tar.c,v 1.31 2008/02/04 20:51:17 christos Exp $") |
|||
#endif |
|||
|
|||
#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') ) |
|||
|
|||
private int is_tar(const unsigned char *, size_t); |
|||
private int from_oct(int, const char *); /* Decode octal number */ |
|||
|
|||
static const char tartype[][32] = { |
|||
"tar archive", |
|||
"POSIX tar archive", |
|||
"POSIX tar archive (GNU)", |
|||
}; |
|||
|
|||
protected int |
|||
file_is_tar(struct magic_set *ms, const unsigned char *buf, size_t nbytes) |
|||
{ |
|||
/* |
|||
* Do the tar test first, because if the first file in the tar |
|||
* archive starts with a dot, we can confuse it with an nroff file. |
|||
*/ |
|||
int tar = is_tar(buf, nbytes); |
|||
int mime = ms->flags & MAGIC_MIME; |
|||
|
|||
if (tar < 1 || tar > 3) |
|||
return 0; |
|||
|
|||
if (mime == MAGIC_MIME_ENCODING) |
|||
return 0; |
|||
|
|||
if (file_printf(ms, mime ? "application/x-tar" : |
|||
tartype[tar - 1]) == -1) |
|||
return -1; |
|||
return 1; |
|||
} |
|||
|
|||
/* |
|||
* Return |
|||
* 0 if the checksum is bad (i.e., probably not a tar archive), |
|||
* 1 for old UNIX tar file, |
|||
* 2 for Unix Std (POSIX) tar file, |
|||
* 3 for GNU tar file. |
|||
*/ |
|||
private int |
|||
is_tar(const unsigned char *buf, size_t nbytes) |
|||
{ |
|||
const union record *header = (const union record *)(const void *)buf; |
|||
int i; |
|||
int sum, recsum; |
|||
const char *p; |
|||
|
|||
if (nbytes < sizeof(union record)) |
|||
return 0; |
|||
|
|||
recsum = from_oct(8, header->header.chksum); |
|||
|
|||
sum = 0; |
|||
p = header->charptr; |
|||
for (i = sizeof(union record); --i >= 0;) { |
|||
/* |
|||
* We cannot use unsigned char here because of old compilers, |
|||
* e.g. V7. |
|||
*/ |
|||
sum += 0xFF & *p++; |
|||
} |
|||
|
|||
/* Adjust checksum to count the "chksum" field as blanks. */ |
|||
for (i = sizeof(header->header.chksum); --i >= 0;) |
|||
sum -= 0xFF & header->header.chksum[i]; |
|||
sum += ' '* sizeof header->header.chksum; |
|||
|
|||
if (sum != recsum) |
|||
return 0; /* Not a tar archive */ |
|||
|
|||
if (strcmp(header->header.magic, GNUTMAGIC) == 0) |
|||
return 3; /* GNU Unix Standard tar archive */ |
|||
if (strcmp(header->header.magic, TMAGIC) == 0) |
|||
return 2; /* Unix Standard tar archive */ |
|||
|
|||
return 1; /* Old fashioned tar archive */ |
|||
} |
|||
|
|||
|
|||
/* |
|||
* Quick and dirty octal conversion. |
|||
* |
|||
* Result is -1 if the field is invalid (all blank, or nonoctal). |
|||
*/ |
|||
private int |
|||
from_oct(int digs, const char *where) |
|||
{ |
|||
int value; |
|||
|
|||
while (isspace((unsigned char)*where)) { /* Skip spaces */ |
|||
where++; |
|||
if (--digs <= 0) |
|||
return -1; /* All blank field */ |
|||
} |
|||
value = 0; |
|||
while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */ |
|||
value = (value << 3) | (*where++ - '0'); |
|||
--digs; |
|||
} |
|||
|
|||
if (digs > 0 && *where && !isspace((unsigned char)*where)) |
|||
return -1; /* Ended on non-space/nul */ |
|||
|
|||
return value; |
|||
} |
|||
@ -0,0 +1,397 @@ |
|||
/* |
|||
* Copyright (c) Christos Zoulas 2003. |
|||
* All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
#include "magic.h" |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
#include <string.h> |
|||
#include <sys/types.h> |
|||
#include <sys/param.h> /* for MAXPATHLEN */ |
|||
#include <sys/stat.h> |
|||
#ifdef QUICK |
|||
#include <sys/mman.h> |
|||
#endif |
|||
#include <limits.h> /* for PIPE_BUF */ |
|||
|
|||
#if defined(HAVE_UTIMES) |
|||
# include <sys/time.h> |
|||
#elif defined(HAVE_UTIME) |
|||
# if defined(HAVE_SYS_UTIME_H) |
|||
# include <sys/utime.h> |
|||
# elif defined(HAVE_UTIME_H) |
|||
# include <utime.h> |
|||
# endif |
|||
#endif |
|||
|
|||
#ifdef HAVE_UNISTD_H |
|||
#include <unistd.h> /* for read() */ |
|||
#endif |
|||
|
|||
#ifdef HAVE_LOCALE_H |
|||
#include <locale.h> |
|||
#endif |
|||
|
|||
#include <netinet/in.h> /* for byte swapping */ |
|||
|
|||
#include "patchlevel.h" |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: magic.c,v 1.50 2008/02/19 00:58:59 rrt Exp $") |
|||
#endif /* lint */ |
|||
|
|||
#ifndef PIPE_BUF |
|||
/* Get the PIPE_BUF from pathconf */ |
|||
#ifdef _PC_PIPE_BUF |
|||
#define PIPE_BUF pathconf(".", _PC_PIPE_BUF) |
|||
#else |
|||
#define PIPE_BUF 512 |
|||
#endif |
|||
#endif |
|||
|
|||
#ifdef __EMX__ |
|||
private char *apptypeName = NULL; |
|||
protected int file_os2_apptype(struct magic_set *ms, const char *fn, |
|||
const void *buf, size_t nb); |
|||
#endif /* __EMX__ */ |
|||
|
|||
private void free_mlist(struct mlist *); |
|||
private void close_and_restore(const struct magic_set *, const char *, int, |
|||
const struct stat *); |
|||
private int info_from_stat(struct magic_set *, mode_t); |
|||
#ifndef COMPILE_ONLY |
|||
private const char *file_or_fd(struct magic_set *, const char *, int); |
|||
#endif |
|||
|
|||
#ifndef STDIN_FILENO |
|||
#define STDIN_FILENO 0 |
|||
#endif |
|||
|
|||
public struct magic_set * |
|||
magic_open(int flags) |
|||
{ |
|||
struct magic_set *ms; |
|||
|
|||
if ((ms = calloc((size_t)1, sizeof(struct magic_set))) == NULL) |
|||
return NULL; |
|||
|
|||
if (magic_setflags(ms, flags) == -1) { |
|||
errno = EINVAL; |
|||
goto free; |
|||
} |
|||
|
|||
ms->o.buf = ms->o.pbuf = NULL; |
|||
|
|||
ms->c.li = malloc((ms->c.len = 10) * sizeof(*ms->c.li)); |
|||
if (ms->c.li == NULL) |
|||
goto free; |
|||
|
|||
ms->haderr = 0; |
|||
ms->error = -1; |
|||
ms->mlist = NULL; |
|||
ms->file = "unknown"; |
|||
ms->line = 0; |
|||
return ms; |
|||
free: |
|||
free(ms); |
|||
return NULL; |
|||
} |
|||
|
|||
private void |
|||
free_mlist(struct mlist *mlist) |
|||
{ |
|||
struct mlist *ml; |
|||
|
|||
if (mlist == NULL) |
|||
return; |
|||
|
|||
for (ml = mlist->next; ml != mlist;) { |
|||
struct mlist *next = ml->next; |
|||
struct magic *mg = ml->magic; |
|||
file_delmagic(mg, ml->mapped, ml->nmagic); |
|||
free(ml); |
|||
ml = next; |
|||
} |
|||
free(ml); |
|||
} |
|||
|
|||
private int |
|||
info_from_stat(struct magic_set *ms, mode_t md) |
|||
{ |
|||
/* We cannot open it, but we were able to stat it. */ |
|||
if (md & 0222) |
|||
if (file_printf(ms, "writable, ") == -1) |
|||
return -1; |
|||
if (md & 0111) |
|||
if (file_printf(ms, "executable, ") == -1) |
|||
return -1; |
|||
if (S_ISREG(md)) |
|||
if (file_printf(ms, "regular file, ") == -1) |
|||
return -1; |
|||
if (file_printf(ms, "no read permission") == -1) |
|||
return -1; |
|||
return 0; |
|||
} |
|||
|
|||
public void |
|||
magic_close(struct magic_set *ms) |
|||
{ |
|||
free_mlist(ms->mlist); |
|||
free(ms->o.pbuf); |
|||
free(ms->o.buf); |
|||
free(ms->c.li); |
|||
free(ms); |
|||
} |
|||
|
|||
/* |
|||
* load a magic file |
|||
*/ |
|||
public int |
|||
magic_load(struct magic_set *ms, const char *magicfile) |
|||
{ |
|||
struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD); |
|||
if (ml) { |
|||
free_mlist(ms->mlist); |
|||
ms->mlist = ml; |
|||
return 0; |
|||
} |
|||
return -1; |
|||
} |
|||
|
|||
public int |
|||
magic_compile(struct magic_set *ms, const char *magicfile) |
|||
{ |
|||
struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE); |
|||
free_mlist(ml); |
|||
return ml ? 0 : -1; |
|||
} |
|||
|
|||
public int |
|||
magic_check(struct magic_set *ms, const char *magicfile) |
|||
{ |
|||
struct mlist *ml = file_apprentice(ms, magicfile, FILE_CHECK); |
|||
free_mlist(ml); |
|||
return ml ? 0 : -1; |
|||
} |
|||
|
|||
private void |
|||
close_and_restore(const struct magic_set *ms, const char *name, int fd, |
|||
const struct stat *sb) |
|||
{ |
|||
if (fd == STDIN_FILENO) |
|||
return; |
|||
(void) close(fd); |
|||
|
|||
if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) { |
|||
/* |
|||
* Try to restore access, modification times if read it. |
|||
* This is really *bad* because it will modify the status |
|||
* time of the file... And of course this will affect |
|||
* backup programs |
|||
*/ |
|||
#ifdef HAVE_UTIMES |
|||
struct timeval utsbuf[2]; |
|||
(void)memset(utsbuf, 0, sizeof(utsbuf)); |
|||
utsbuf[0].tv_sec = sb->st_atime; |
|||
utsbuf[1].tv_sec = sb->st_mtime; |
|||
|
|||
(void) utimes(name, utsbuf); /* don't care if loses */ |
|||
#elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H) |
|||
struct utimbuf utbuf; |
|||
|
|||
(void)memset(utbuf, 0, sizeof(utbuf)); |
|||
utbuf.actime = sb->st_atime; |
|||
utbuf.modtime = sb->st_mtime; |
|||
(void) utime(name, &utbuf); /* don't care if loses */ |
|||
#endif |
|||
} |
|||
} |
|||
|
|||
#ifndef COMPILE_ONLY |
|||
|
|||
/* |
|||
* find type of descriptor |
|||
*/ |
|||
public const char * |
|||
magic_descriptor(struct magic_set *ms, int fd) |
|||
{ |
|||
return file_or_fd(ms, NULL, fd); |
|||
} |
|||
|
|||
/* |
|||
* find type of named file |
|||
*/ |
|||
public const char * |
|||
magic_file(struct magic_set *ms, const char *inname) |
|||
{ |
|||
return file_or_fd(ms, inname, STDIN_FILENO); |
|||
} |
|||
|
|||
private const char * |
|||
file_or_fd(struct magic_set *ms, const char *inname, int fd) |
|||
{ |
|||
int rv = -1; |
|||
unsigned char *buf; |
|||
struct stat sb; |
|||
ssize_t nbytes = 0; /* number of bytes read from a datafile */ |
|||
int ispipe = 0; |
|||
|
|||
/* |
|||
* one extra for terminating '\0', and |
|||
* some overlapping space for matches near EOF |
|||
*/ |
|||
#define SLOP (1 + sizeof(union VALUETYPE)) |
|||
if ((buf = malloc(HOWMANY + SLOP)) == NULL) |
|||
return NULL; |
|||
|
|||
if (file_reset(ms) == -1) |
|||
goto done; |
|||
|
|||
switch (file_fsmagic(ms, inname, &sb)) { |
|||
case -1: /* error */ |
|||
goto done; |
|||
case 0: /* nothing found */ |
|||
break; |
|||
default: /* matched it and printed type */ |
|||
rv = 0; |
|||
goto done; |
|||
} |
|||
|
|||
if (inname == NULL) { |
|||
if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) |
|||
ispipe = 1; |
|||
} else { |
|||
int flags = O_RDONLY|O_BINARY; |
|||
|
|||
if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) { |
|||
flags |= O_NONBLOCK; |
|||
ispipe = 1; |
|||
} |
|||
|
|||
errno = 0; |
|||
if ((fd = open(inname, flags)) < 0) { |
|||
#ifdef __CYGWIN__ |
|||
/* FIXME: Do this with EXEEXT from autotools */ |
|||
char *tmp = alloca(strlen(inname) + 5); |
|||
(void)strcat(strcpy(tmp, inname), ".exe"); |
|||
if ((fd = open(tmp, flags)) < 0) { |
|||
#endif |
|||
fprintf(stderr, "couldn't open file\n"); |
|||
if (info_from_stat(ms, sb.st_mode) == -1) |
|||
goto done; |
|||
rv = 0; |
|||
goto done; |
|||
#ifdef __CYGWIN__ |
|||
} |
|||
#endif |
|||
} |
|||
#ifdef O_NONBLOCK |
|||
if ((flags = fcntl(fd, F_GETFL)) != -1) { |
|||
flags &= ~O_NONBLOCK; |
|||
(void)fcntl(fd, F_SETFL, flags); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
/* |
|||
* try looking at the first HOWMANY bytes |
|||
*/ |
|||
if (ispipe) { |
|||
ssize_t r = 0; |
|||
|
|||
while ((r = sread(fd, (void *)&buf[nbytes], |
|||
(size_t)(HOWMANY - nbytes), 1)) > 0) { |
|||
nbytes += r; |
|||
if (r < PIPE_BUF) break; |
|||
} |
|||
|
|||
if (nbytes == 0) { |
|||
/* We can not read it, but we were able to stat it. */ |
|||
if (info_from_stat(ms, sb.st_mode) == -1) |
|||
goto done; |
|||
rv = 0; |
|||
goto done; |
|||
} |
|||
|
|||
} else { |
|||
if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) { |
|||
file_error(ms, errno, "cannot read `%s'", inname); |
|||
goto done; |
|||
} |
|||
} |
|||
|
|||
(void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */ |
|||
if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1) |
|||
goto done; |
|||
rv = 0; |
|||
done: |
|||
free(buf); |
|||
close_and_restore(ms, inname, fd, &sb); |
|||
return rv == 0 ? file_getbuffer(ms) : NULL; |
|||
} |
|||
|
|||
|
|||
public const char * |
|||
magic_buffer(struct magic_set *ms, const void *buf, size_t nb) |
|||
{ |
|||
if (file_reset(ms) == -1) |
|||
return NULL; |
|||
/* |
|||
* The main work is done here! |
|||
* We have the file name and/or the data buffer to be identified. |
|||
*/ |
|||
if (file_buffer(ms, -1, NULL, buf, nb) == -1) { |
|||
return NULL; |
|||
} |
|||
return file_getbuffer(ms); |
|||
} |
|||
#endif |
|||
|
|||
public const char * |
|||
magic_error(struct magic_set *ms) |
|||
{ |
|||
return ms->haderr ? ms->o.buf : NULL; |
|||
} |
|||
|
|||
public int |
|||
magic_errno(struct magic_set *ms) |
|||
{ |
|||
return ms->haderr ? ms->error : 0; |
|||
} |
|||
|
|||
public int |
|||
magic_setflags(struct magic_set *ms, int flags) |
|||
{ |
|||
#if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES) |
|||
if (flags & MAGIC_PRESERVE_ATIME) |
|||
return -1; |
|||
#endif |
|||
ms->flags = flags; |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
/* |
|||
* Copyright (c) Christos Zoulas 2003. |
|||
* All Rights Reserved. |
|||
* |
|||
* 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 _MAGIC_H |
|||
#define _MAGIC_H |
|||
|
|||
#include <sys/types.h> |
|||
|
|||
#define MAGIC_NONE 0x000000 /* No flags */ |
|||
#define MAGIC_DEBUG 0x000001 /* Turn on debugging */ |
|||
#define MAGIC_SYMLINK 0x000002 /* Follow symlinks */ |
|||
#define MAGIC_COMPRESS 0x000004 /* Check inside compressed files */ |
|||
#define MAGIC_DEVICES 0x000008 /* Look at the contents of devices */ |
|||
#define MAGIC_MIME_TYPE 0x000010 /* Return only the MIME type */ |
|||
#define MAGIC_CONTINUE 0x000020 /* Return all matches */ |
|||
#define MAGIC_CHECK 0x000040 /* Print warnings to stderr */ |
|||
#define MAGIC_PRESERVE_ATIME 0x000080 /* Restore access time on exit */ |
|||
#define MAGIC_RAW 0x000100 /* Don't translate unprint chars */ |
|||
#define MAGIC_ERROR 0x000200 /* Handle ENOENT etc as real errors */ |
|||
#define MAGIC_MIME_ENCODING 0x000400 /* Return only the MIME encoding */ |
|||
#define MAGIC_MIME (MAGIC_MIME_TYPE|MAGIC_MIME_ENCODING) |
|||
#define MAGIC_NO_CHECK_COMPRESS 0x001000 /* Don't check for compressed files */ |
|||
#define MAGIC_NO_CHECK_TAR 0x002000 /* Don't check for tar files */ |
|||
#define MAGIC_NO_CHECK_SOFT 0x004000 /* Don't check magic entries */ |
|||
#define MAGIC_NO_CHECK_APPTYPE 0x008000 /* Don't check application type */ |
|||
#define MAGIC_NO_CHECK_ELF 0x010000 /* Don't check for elf details */ |
|||
#define MAGIC_NO_CHECK_ASCII 0x020000 /* Don't check for ascii files */ |
|||
#define MAGIC_NO_CHECK_TOKENS 0x100000 /* Don't check ascii/tokens */ |
|||
|
|||
/* Defined for backwards compatibility; do nothing */ |
|||
#define MAGIC_NO_CHECK_FORTRAN 0x000000 /* Don't check ascii/fortran */ |
|||
#define MAGIC_NO_CHECK_TROFF 0x000000 /* Don't check ascii/troff */ |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
typedef struct magic_set *magic_t; |
|||
magic_t magic_open(int); |
|||
void magic_close(magic_t); |
|||
|
|||
const char *magic_file(magic_t, const char *); |
|||
const char *magic_descriptor(magic_t, int); |
|||
const char *magic_buffer(magic_t, const void *, size_t); |
|||
|
|||
const char *magic_error(magic_t); |
|||
int magic_setflags(magic_t, int); |
|||
|
|||
int magic_load(magic_t, const char *); |
|||
int magic_compile(magic_t, const char *); |
|||
int magic_check(magic_t, const char *); |
|||
int magic_errno(magic_t); |
|||
|
|||
#ifdef __cplusplus |
|||
}; |
|||
#endif |
|||
|
|||
#endif /* _MAGIC_H */ |
|||
@ -0,0 +1,173 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* Names.h - names and types used by ascmagic in file(1). |
|||
* These tokens are here because they can appear anywhere in |
|||
* the first HOWMANY bytes, while tokens in MAGIC must |
|||
* appear at fixed offsets into the file. Don't make HOWMANY |
|||
* too high unless you have a very fast CPU. |
|||
* |
|||
* $File: names.h,v 1.32 2008/02/11 00:19:29 rrt Exp $ |
|||
*/ |
|||
|
|||
/* |
|||
modified by Chris Lowth - 9 April 2000 |
|||
to add mime type strings to the types table. |
|||
*/ |
|||
|
|||
/* these types are used to index the table 'types': keep em in sync! */ |
|||
#define L_C 0 /* first and foremost on UNIX */ |
|||
#define L_CC 1 /* Bjarne's postincrement */ |
|||
#define L_MAKE 2 /* Makefiles */ |
|||
#define L_PLI 3 /* PL/1 */ |
|||
#define L_MACH 4 /* some kinda assembler */ |
|||
#define L_ENG 5 /* English */ |
|||
#define L_PAS 6 /* Pascal */ |
|||
#define L_MAIL 7 /* Electronic mail */ |
|||
#define L_NEWS 8 /* Usenet Netnews */ |
|||
#define L_JAVA 9 /* Java code */ |
|||
#define L_HTML 10 /* HTML */ |
|||
#define L_BCPL 11 /* BCPL */ |
|||
#define L_M4 12 /* M4 */ |
|||
#define L_PO 13 /* PO */ |
|||
|
|||
static const struct { |
|||
char human[48]; |
|||
char mime[16]; |
|||
} types[] = { |
|||
{ "C program", "text/x-c", }, |
|||
{ "C++ program", "text/x-c++" }, |
|||
{ "make commands", "text/x-makefile" }, |
|||
{ "PL/1 program", "text/x-pl1" }, |
|||
{ "assembler program", "text/x-asm" }, |
|||
{ "English", "text/plain" }, |
|||
{ "Pascal program", "text/x-pascal" }, |
|||
{ "mail", "text/x-mail" }, |
|||
{ "news", "text/x-news" }, |
|||
{ "Java program", "text/x-java" }, |
|||
{ "HTML document", "text/html", }, |
|||
{ "BCPL program", "text/x-bcpl" }, |
|||
{ "M4 macro language pre-processor", "text/x-m4" }, |
|||
{ "PO (gettext message catalogue)", "text/x-po" }, |
|||
{ "cannot happen error on names.h/types", "error/x-error" } |
|||
}; |
|||
|
|||
/* |
|||
* XXX - how should we distinguish Java from C++? |
|||
* The trick used in a Debian snapshot, of having "extends" or "implements" |
|||
* as tags for Java, doesn't work very well, given that those keywords |
|||
* are often preceded by "class", which flags it as C++. |
|||
* |
|||
* Perhaps we need to be able to say |
|||
* |
|||
* If "class" then |
|||
* |
|||
* if "extends" or "implements" then |
|||
* Java |
|||
* else |
|||
* C++ |
|||
* endif |
|||
* |
|||
* Or should we use other keywords, such as "package" or "import"? |
|||
* Unfortunately, Ada95 uses "package", and Modula-3 uses "import", |
|||
* although I infer from the language spec at |
|||
* |
|||
* http://www.research.digital.com/SRC/m3defn/html/m3.html |
|||
* |
|||
* that Modula-3 uses "IMPORT" rather than "import", i.e. it must be |
|||
* in all caps. |
|||
* |
|||
* So, for now, we go with "import". We must put it before the C++ |
|||
* stuff, so that we don't misidentify Java as C++. Not using "package" |
|||
* means we won't identify stuff that defines a package but imports |
|||
* nothing; hopefully, very little Java code imports nothing (one of the |
|||
* reasons for doing OO programming is to import as much as possible |
|||
* and write only what you need to, right?). |
|||
* |
|||
* Unfortunately, "import" may cause us to misidentify English text |
|||
* as Java, as it comes after "the" and "The". Perhaps we need a fancier |
|||
* heuristic to identify Java? |
|||
*/ |
|||
static const struct names { |
|||
char name[14]; |
|||
short type; |
|||
} names[] = { |
|||
/* These must be sorted by eye for optimal hit rate */ |
|||
/* Add to this list only after substantial meditation */ |
|||
{"msgid", L_PO}, |
|||
{"dnl", L_M4}, |
|||
{"import", L_JAVA}, |
|||
{"\"libhdr\"", L_BCPL}, |
|||
{"\"LIBHDR\"", L_BCPL}, |
|||
{"//", L_CC}, |
|||
{"template", L_CC}, |
|||
{"virtual", L_CC}, |
|||
{"class", L_CC}, |
|||
{"public:", L_CC}, |
|||
{"private:", L_CC}, |
|||
{"/*", L_C}, /* must precede "The", "the", etc. */ |
|||
{"#include", L_C}, |
|||
{"char", L_C}, |
|||
{"The", L_ENG}, |
|||
{"the", L_ENG}, |
|||
{"double", L_C}, |
|||
{"extern", L_C}, |
|||
{"float", L_C}, |
|||
{"struct", L_C}, |
|||
{"union", L_C}, |
|||
{"CFLAGS", L_MAKE}, |
|||
{"LDFLAGS", L_MAKE}, |
|||
{"all:", L_MAKE}, |
|||
{".PRECIOUS", L_MAKE}, |
|||
{".ascii", L_MACH}, |
|||
{".asciiz", L_MACH}, |
|||
{".byte", L_MACH}, |
|||
{".even", L_MACH}, |
|||
{".globl", L_MACH}, |
|||
{".text", L_MACH}, |
|||
{"clr", L_MACH}, |
|||
{"(input,", L_PAS}, |
|||
{"program", L_PAS}, |
|||
{"record", L_PAS}, |
|||
{"dcl", L_PLI}, |
|||
{"Received:", L_MAIL}, |
|||
{">From", L_MAIL}, |
|||
{"Return-Path:",L_MAIL}, |
|||
{"Cc:", L_MAIL}, |
|||
{"Newsgroups:", L_NEWS}, |
|||
{"Path:", L_NEWS}, |
|||
{"Organization:",L_NEWS}, |
|||
{"href=", L_HTML}, |
|||
{"HREF=", L_HTML}, |
|||
{"<body", L_HTML}, |
|||
{"<BODY", L_HTML}, |
|||
{"<html", L_HTML}, |
|||
{"<HTML", L_HTML}, |
|||
{"<!--", L_HTML}, |
|||
}; |
|||
#define NNAMES (sizeof(names)/sizeof(struct names)) |
|||
@ -0,0 +1,337 @@ |
|||
#define FILE_VERSION_MAJOR 4 |
|||
#define patchlevel 24 |
|||
|
|||
/* |
|||
* Patchlevel file for Ian Darwin's MAGIC command. |
|||
* $File: patchlevel.h,v 1.68 2008/03/22 21:39:43 christos Exp $ |
|||
* |
|||
* $Log$ |
|||
* Revision 1.1 2008/07/11 14:10:50 derick |
|||
* - Step one for bundling the libmagic library. Some config.m4 issues left. |
|||
* |
|||
* Revision 1.68 2008/03/22 21:39:43 christos |
|||
* file 4.24 |
|||
* |
|||
* Revision 1.67 2007/12/28 20:08:40 christos |
|||
* welcome to 4.23. |
|||
* |
|||
* Revision 1.66 2007/12/27 16:38:24 christos |
|||
* welcome to 4.22 |
|||
* |
|||
* Revision 1.65 2007/05/24 17:22:27 christos |
|||
* Welcome to 4.21 |
|||
* |
|||
* Revision 1.64 2007/03/01 22:14:55 christos |
|||
* welcome to 4.20 |
|||
* |
|||
* Revision 1.63 2007/01/12 17:38:28 christos |
|||
* Use File id. |
|||
* |
|||
* Revision 1.62 2006/12/11 21:49:58 christos |
|||
* time for 4.19 |
|||
* |
|||
* Revision 1.61 2006/10/31 21:18:09 christos |
|||
* bump |
|||
* |
|||
* Revision 1.60 2006/03/02 22:15:12 christos |
|||
* welcome to 4.17 |
|||
* |
|||
* Revision 1.59 2005/10/17 17:15:21 christos |
|||
* welcome to 4.16 |
|||
* |
|||
* Revision 1.58 2005/08/18 15:52:56 christos |
|||
* welcome to 4.15 |
|||
* |
|||
* Revision 1.57 2005/06/25 15:52:14 christos |
|||
* Welcome to 4.14 |
|||
* |
|||
* Revision 1.56 2005/02/09 19:25:13 christos |
|||
* Welcome to 4.13 |
|||
* |
|||
* Revision 1.55 2004/11/24 18:57:47 christos |
|||
* Re-do the autoconf stuff once more; passes make dist now. |
|||
* |
|||
* Revision 1.54 2004/11/21 05:52:05 christos |
|||
* ready for 4.11 |
|||
* |
|||
* Revision 1.53 2004/07/24 20:40:46 christos |
|||
* welcome to 4.10 |
|||
* |
|||
* Revision 1.52 2004/04/07 00:32:25 christos |
|||
* welcome to 4.09 |
|||
* |
|||
* Revision 1.51 2004/03/22 21:17:11 christos |
|||
* welcome to 4.08. |
|||
* |
|||
* Revision 1.50 2003/12/23 17:34:04 christos |
|||
* 4.07 |
|||
* |
|||
* Revision 1.49 2003/10/15 02:08:27 christos |
|||
* welcome to 4.06 |
|||
* |
|||
* Revision 1.48 2003/09/12 19:41:14 christos |
|||
* this is 4.04 |
|||
* |
|||
* Revision 1.47 2003/05/23 21:38:21 christos |
|||
* welcome to 4.03 |
|||
* |
|||
* Revision 1.46 2003/04/02 18:57:43 christos |
|||
* prepare for 4.02 |
|||
* |
|||
* Revision 1.45 2003/03/26 15:37:25 christos |
|||
* - Pass lint |
|||
* - make NULL in magic_file mean stdin |
|||
* - Fix "-" argument to file to pass NULL to magic_file |
|||
* - avoid pointer casts by using memcpy |
|||
* - rename magic_buf -> magic_buffer |
|||
* - keep only the first error |
|||
* - manual page: new sentence, new line |
|||
* - fix typo in api function (magic_buf -> magic_buffer) |
|||
* |
|||
* Revision 1.44 2003/03/23 22:23:31 christos |
|||
* finish librarification. |
|||
* |
|||
* Revision 1.43 2003/03/23 21:16:26 christos |
|||
* update copyrights. |
|||
* |
|||
* Revision 1.42 2003/03/23 04:06:05 christos |
|||
* Library re-organization |
|||
* |
|||
* Revision 1.41 2003/02/27 20:53:45 christos |
|||
* - fix memory allocation problem (Jeff Johnson) |
|||
* - fix stack overflow corruption (David Endler) |
|||
* - fixes from NetBSD source (Antti Kantee) |
|||
* - magic fixes |
|||
* |
|||
* Revision 1.40 2003/02/08 18:33:53 christos |
|||
* - detect inttypes.h too (Dave Love <d.love@dl.ac.uk>) |
|||
* - eliminate unsigned char warnings (Petter Reinholdtsen <pere@hungry.com>) |
|||
* - better elf PT_NOTE handling (Nalin Dahyabhai <nalin@redhat.com>) |
|||
* - add options to format the output differently |
|||
* - much more magic. |
|||
* |
|||
* Revision 1.39 2002/07/03 18:57:52 christos |
|||
* - ansify/c99ize |
|||
* - more magic |
|||
* - better COMPILE_ONLY support. |
|||
* - new magic files. |
|||
* - fix solaris compilation problems. |
|||
* |
|||
* Revision 1.38 2002/05/16 18:45:56 christos |
|||
* - pt_note elf additions from NetBSD |
|||
* - EMX os specific changes (Alexander Mai) |
|||
* - stdint.h detection, acconfig.h fixes (Maciej W. Rozycki, Franz Korntner) |
|||
* - regex file additions (Kim Cromie) |
|||
* - getopt_long support and misc cleanups (Michael Piefel) |
|||
* - many magic fixes and additions |
|||
* |
|||
* Revision 1.37 2001/09/03 14:44:22 christos |
|||
* daylight/tm_isdst detection |
|||
* magic fixes |
|||
* don't eat the whole file if it has only nulls |
|||
* |
|||
* Revision 1.36 2001/07/22 21:04:15 christos |
|||
* - magic fixes |
|||
* - add new operators, pascal strings, UTC date printing, $HOME/.magic |
|||
* [from "Tom N Harris" <telliamed@mac.com>] |
|||
* |
|||
* Revision 1.35 2001/04/24 14:40:25 christos |
|||
* - rename magic file sgi to mips and fix it |
|||
* - add support for building magic.mgc |
|||
* - portability fixes for mmap() |
|||
* - try gzip before uncompress, because uncompress sometimes hangs |
|||
* - be more conservative about pipe reads and writes |
|||
* - many magic fixes |
|||
* |
|||
* Revision 1.34 2001/03/12 05:05:57 christos |
|||
* - new compiled magic format |
|||
* - lots of magic additions |
|||
* |
|||
* Revision 1.33 2000/11/13 00:30:50 christos |
|||
* - wordperfect magic fix: freebsd pr 9388 |
|||
* - more msdos fixes from freebsd pr's 20131 and 20812 |
|||
* - sas and spss magic [Bruce Foster] |
|||
* - mkinstalldirs [John Fremlin] |
|||
* - sgi opengl fixes [Michael Pruett] |
|||
* - netbsd magic fixes [Ignatios Souvatzis] |
|||
* - audio additions [Michael Pruett] |
|||
* - fix problem with non ansi RCSID [Andreas Ley] |
|||
* - oggs magic [Felix von Leitner] |
|||
* - gmon magic [Eugen Dedu] |
|||
* - TNEF magic [Joomy] |
|||
* - netpbm magic and misc other image stuff [Bryan Henderson] |
|||
* |
|||
* Revision 1.32 2000/08/05 18:24:18 christos |
|||
* Correct indianness detection in elf (Charles Hannum) |
|||
* FreeBSD elf core support (Guy Harris) |
|||
* Use gzip in systems that don't have uncompress (Anthon van der Neut) |
|||
* Internationalization/EBCDIC support (Eric Fisher) |
|||
* Many many magic changes |
|||
* |
|||
* Revision 1.31 2000/05/14 17:58:36 christos |
|||
* - new magic for claris files |
|||
* - new magic for mathematica and maple files |
|||
* - new magic for msvc files |
|||
* - new -k flag to keep going matching all possible entries |
|||
* - add the word executable on #! magic files, and fix the usage of |
|||
* the word script |
|||
* - lots of other magic fixes |
|||
* - fix typo test -> text |
|||
* |
|||
* Revision 1.30 2000/04/11 02:41:17 christos |
|||
* - add support for mime output (-i) |
|||
* - make sure we free memory in case realloc fails |
|||
* - magic fixes |
|||
* |
|||
* Revision 1.29 1999/11/28 20:02:29 christos |
|||
* new string/[Bcb] magic from anthon, and adjustments to the magic files to |
|||
* use it. |
|||
* |
|||
* Revision 1.28 1999/10/31 22:11:48 christos |
|||
* - add "char" type for compatibility with HP/UX |
|||
* - recognize HP/UX syntax &=n etc. |
|||
* - include errno.h for CYGWIN |
|||
* - conditionalize the S_IS* macros |
|||
* - revert the SHT_DYNSYM test that broke the linux stripped binaries test |
|||
* - lots of Magdir changes |
|||
* |
|||
* Revision 1.27 1999/02/14 17:21:41 christos |
|||
* Automake support and misc cleanups from Rainer Orth |
|||
* Enable reading character and block special files from Dale R. Worley |
|||
* |
|||
* Revision 1.26 1998/09/12 13:19:39 christos |
|||
* - add support for bi-endian indirect offsets (Richard Verhoeven) |
|||
* - add recognition for bcpl (Joseph Myers) |
|||
* - remove non magic files from Magdir to avoid difficulties building |
|||
* on os2 where files are case independent |
|||
* - magic fixes. |
|||
* |
|||
* Revision 1.25 1998/06/27 14:04:04 christos |
|||
* OLF patch Guy Harris |
|||
* Recognize java/html (debian linux) |
|||
* Const poisoning (debian linux) |
|||
* More magic! |
|||
* |
|||
* Revision 1.24 1998/02/15 23:20:38 christos |
|||
* Autoconf patch: Felix von Leitner <leitner@math.fu-berlin.de> |
|||
* More magic fixes |
|||
* Elf64 fixes |
|||
* |
|||
* Revision 1.23 1997/11/05 16:03:37 christos |
|||
* - correct elf prps offset for SunOS-2.5.1 [guy@netapp.com] |
|||
* - handle 64 bit time_t's correctly [ewt@redhat.com] |
|||
* - new mime style magic [clarosse@netvista.net] |
|||
* - new TI calculator magic [rmcguire@freenet.columbus.oh.us] |
|||
* - new figlet fonts [obrien@freebsd.org] |
|||
* - new cisco magic, and elf fixes [jhawk@bbnplanet.com] |
|||
* - -b flag addition, and x86 filesystem magic [vax@linkhead.paranoia.com] |
|||
* - s/Mpeg/MPEG, header and elf typo fixes [guy@netapp.com] |
|||
* - Windows/NT registry files, audio code [guy@netapp.com] |
|||
* - libGrx graphics lib fonts [guy@netapp.com] |
|||
* - PNG fixes [guy@netapp.com] |
|||
* - more m$ document magic [guy@netapp.com] |
|||
* - PPD files [guy@netapp.com] |
|||
* - archive magic cleanup [guy@netapp.com] |
|||
* - linux kernel magic cleanup [guy@netapp.com] |
|||
* - lecter magic [guy@netapp.com] |
|||
* - vgetty magic [guy@netapp.com] |
|||
* - sniffer additions [guy@netapp.com] |
|||
* |
|||
* Revision 1.22 1997/01/15 17:23:24 christos |
|||
* - add support for elf core files: find the program name under SVR4 [Ken Pizzini] |
|||
* - print strings only up to the first carriage return [various] |
|||
* - freebsd international ascii support [J Wunsch] |
|||
* - magic fixes and additions [Guy Harris] |
|||
* - 64 bit fixes [Larry Schwimmer] |
|||
* - support for both utime and utimes, but don't restore file access times |
|||
* by default [various] |
|||
* - \xXX only takes 2 hex digits, not 3. |
|||
* - re-implement support for core files [Guy Harris] |
|||
* |
|||
* Revision 1.21 1996/10/05 18:15:29 christos |
|||
* Segregate elf stuff and conditionally enable it with -DBUILTIN_ELF |
|||
* More magic fixes |
|||
* |
|||
* Revision 1.20 1996/06/22 22:15:52 christos |
|||
* - support relative offsets of the form >& |
|||
* - fix bug with truncating magic strings that contain \n |
|||
* - file -f - did not read from stdin as documented |
|||
* - support elf file parsing using our own elf support. |
|||
* - as always magdir fixes and additions. |
|||
* |
|||
* Revision 1.19 1995/10/27 23:14:46 christos |
|||
* Ability to parse colon separated list of magic files |
|||
* New LEGAL.NOTICE |
|||
* Various magic file changes |
|||
* |
|||
* Revision 1.18 1995/05/20 22:09:21 christos |
|||
* Passed incorrect argument to eatsize(). |
|||
* Use %ld and %lx where appropriate. |
|||
* Remove unused variables |
|||
* ELF support for both big and little endian |
|||
* Fixes for small files again. |
|||
* |
|||
* Revision 1.17 1995/04/28 17:29:13 christos |
|||
* - Incorrect nroff detection fix from der Mouse |
|||
* - Lost and incorrect magic entries. |
|||
* - Added ELF stripped binary detection [in C; ugh] |
|||
* - Look for $MAGIC to find the magic file. |
|||
* - Eat trailing size specifications from numbers i.e. ignore 10L |
|||
* - More fixes for very short files |
|||
* |
|||
* Revision 1.16 1995/03/25 22:06:45 christos |
|||
* - use strtoul() where it exists. |
|||
* - fix sign-extend bug |
|||
* - try to detect tar archives before nroff files, otherwise |
|||
* tar files where the first file starts with a . will not work |
|||
* |
|||
* Revision 1.15 1995/01/21 21:03:35 christos |
|||
* Added CSECTION for the file man page |
|||
* Added version flag -v |
|||
* Fixed bug with -f input flag (from iorio@violet.berkeley.edu) |
|||
* Lots of magic fixes and reorganization... |
|||
* |
|||
* Revision 1.14 1994/05/03 17:58:23 christos |
|||
* changes from mycroft@gnu.ai.mit.edu (Charles Hannum) for unsigned |
|||
* |
|||
* Revision 1.13 1994/01/21 01:27:01 christos |
|||
* Fixed null termination bug from Don Seeley at BSDI in ascmagic.c |
|||
* |
|||
* Revision 1.12 1993/10/27 20:59:05 christos |
|||
* Changed -z flag to understand gzip format too. |
|||
* Moved builtin compression detection to a table, and move |
|||
* the compress magic entry out of the source. |
|||
* Made printing of numbers unsigned, and added the mask to it. |
|||
* Changed the buffer size to 8k, because gzip will refuse to |
|||
* unzip just a few bytes. |
|||
* |
|||
* Revision 1.11 1993/09/24 18:49:06 christos |
|||
* Fixed small bug in softmagic.c introduced by |
|||
* copying the data to be examined out of the input |
|||
* buffer. Changed the Makefile to use sed to create |
|||
* the correct man pages. |
|||
* |
|||
* Revision 1.10 1993/09/23 21:56:23 christos |
|||
* Passed purify. Fixed indirections. Fixed byte order printing. |
|||
* Fixed segmentation faults caused by referencing past the end |
|||
* of the magic buffer. Fixed bus errors caused by referencing |
|||
* unaligned shorts or longs. |
|||
* |
|||
* Revision 1.9 1993/03/24 14:23:40 ian |
|||
* Batch of minor changes from several contributors. |
|||
* |
|||
* Revision 1.8 93/02/19 15:01:26 ian |
|||
* Numerous changes from Guy Harris too numerous to mention but including |
|||
* byte-order independance, fixing "old-style masking", etc. etc. A bugfix |
|||
* for broken symlinks from martin@@d255s004.zfe.siemens.de. |
|||
* |
|||
* Revision 1.7 93/01/05 14:57:27 ian |
|||
* Couple of nits picked by Christos (again, thanks). |
|||
* |
|||
* Revision 1.6 93/01/05 13:51:09 ian |
|||
* Lotsa work on the Magic directory. |
|||
* |
|||
* Revision 1.5 92/09/14 14:54:51 ian |
|||
* Fix a tiny null-pointer bug in previous fix for tar archive + uncompress. |
|||
* |
|||
*/ |
|||
@ -0,0 +1,236 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* print.c - debugging printout routines |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
#include <stdio.h> |
|||
#include <errno.h> |
|||
#include <string.h> |
|||
#include <stdarg.h> |
|||
#include <stdlib.h> |
|||
#ifdef HAVE_UNISTD_H |
|||
#include <unistd.h> |
|||
#endif |
|||
#include <time.h> |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: print.c,v 1.63 2008/02/17 19:28:54 rrt Exp $") |
|||
#endif /* lint */ |
|||
|
|||
#define SZOF(a) (sizeof(a) / sizeof(a[0])) |
|||
|
|||
#ifndef COMPILE_ONLY |
|||
protected void |
|||
file_mdump(struct magic *m) |
|||
{ |
|||
private const char optyp[] = { FILE_OPS }; |
|||
|
|||
(void) fprintf(stderr, "[%u", m->lineno); |
|||
(void) fprintf(stderr, ">>>>>>>> %u" + 8 - (m->cont_level & 7), |
|||
m->offset); |
|||
|
|||
if (m->flag & INDIR) { |
|||
(void) fprintf(stderr, "(%s,", |
|||
/* Note: type is unsigned */ |
|||
(m->in_type < file_nnames) ? |
|||
file_names[m->in_type] : "*bad*"); |
|||
if (m->in_op & FILE_OPINVERSE) |
|||
(void) fputc('~', stderr); |
|||
(void) fprintf(stderr, "%c%u),", |
|||
((m->in_op & FILE_OPS_MASK) < SZOF(optyp)) ? |
|||
optyp[m->in_op & FILE_OPS_MASK] : '?', |
|||
m->in_offset); |
|||
} |
|||
(void) fprintf(stderr, " %s%s", (m->flag & UNSIGNED) ? "u" : "", |
|||
/* Note: type is unsigned */ |
|||
(m->type < file_nnames) ? file_names[m->type] : "*bad*"); |
|||
if (m->mask_op & FILE_OPINVERSE) |
|||
(void) fputc('~', stderr); |
|||
|
|||
if (IS_STRING(m->type)) { |
|||
if (m->str_flags) { |
|||
(void) fputc('/', stderr); |
|||
if (m->str_flags & STRING_COMPACT_BLANK) |
|||
(void) fputc(CHAR_COMPACT_BLANK, stderr); |
|||
if (m->str_flags & STRING_COMPACT_OPTIONAL_BLANK) |
|||
(void) fputc(CHAR_COMPACT_OPTIONAL_BLANK, |
|||
stderr); |
|||
if (m->str_flags & STRING_IGNORE_LOWERCASE) |
|||
(void) fputc(CHAR_IGNORE_LOWERCASE, stderr); |
|||
if (m->str_flags & STRING_IGNORE_UPPERCASE) |
|||
(void) fputc(CHAR_IGNORE_UPPERCASE, stderr); |
|||
if (m->str_flags & REGEX_OFFSET_START) |
|||
(void) fputc(CHAR_REGEX_OFFSET_START, stderr); |
|||
} |
|||
if (m->str_range) |
|||
(void) fprintf(stderr, "/%u", m->str_range); |
|||
} |
|||
else { |
|||
if ((m->mask_op & FILE_OPS_MASK) < SZOF(optyp)) |
|||
(void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr); |
|||
else |
|||
(void) fputc('?', stderr); |
|||
|
|||
if (m->num_mask) { |
|||
(void) fprintf(stderr, "%.8llx", |
|||
(unsigned long long)m->num_mask); |
|||
} |
|||
} |
|||
(void) fprintf(stderr, ",%c", m->reln); |
|||
|
|||
if (m->reln != 'x') { |
|||
switch (m->type) { |
|||
case FILE_BYTE: |
|||
case FILE_SHORT: |
|||
case FILE_LONG: |
|||
case FILE_LESHORT: |
|||
case FILE_LELONG: |
|||
case FILE_MELONG: |
|||
case FILE_BESHORT: |
|||
case FILE_BELONG: |
|||
(void) fprintf(stderr, "%d", m->value.l); |
|||
break; |
|||
case FILE_BEQUAD: |
|||
case FILE_LEQUAD: |
|||
case FILE_QUAD: |
|||
(void) fprintf(stderr, "%lld", |
|||
(unsigned long long)m->value.q); |
|||
break; |
|||
case FILE_PSTRING: |
|||
case FILE_STRING: |
|||
case FILE_REGEX: |
|||
case FILE_BESTRING16: |
|||
case FILE_LESTRING16: |
|||
case FILE_SEARCH: |
|||
file_showstr(stderr, m->value.s, (size_t)m->vallen); |
|||
break; |
|||
case FILE_DATE: |
|||
case FILE_LEDATE: |
|||
case FILE_BEDATE: |
|||
case FILE_MEDATE: |
|||
(void)fprintf(stderr, "%s,", |
|||
file_fmttime(m->value.l, 1)); |
|||
break; |
|||
case FILE_LDATE: |
|||
case FILE_LELDATE: |
|||
case FILE_BELDATE: |
|||
case FILE_MELDATE: |
|||
(void)fprintf(stderr, "%s,", |
|||
file_fmttime(m->value.l, 0)); |
|||
break; |
|||
case FILE_QDATE: |
|||
case FILE_LEQDATE: |
|||
case FILE_BEQDATE: |
|||
(void)fprintf(stderr, "%s,", |
|||
file_fmttime((uint32_t)m->value.q, 1)); |
|||
break; |
|||
case FILE_QLDATE: |
|||
case FILE_LEQLDATE: |
|||
case FILE_BEQLDATE: |
|||
(void)fprintf(stderr, "%s,", |
|||
file_fmttime((uint32_t)m->value.q, 0)); |
|||
break; |
|||
case FILE_FLOAT: |
|||
case FILE_BEFLOAT: |
|||
case FILE_LEFLOAT: |
|||
(void) fprintf(stderr, "%G", m->value.f); |
|||
break; |
|||
case FILE_DOUBLE: |
|||
case FILE_BEDOUBLE: |
|||
case FILE_LEDOUBLE: |
|||
(void) fprintf(stderr, "%G", m->value.d); |
|||
break; |
|||
case FILE_DEFAULT: |
|||
/* XXX - do anything here? */ |
|||
break; |
|||
default: |
|||
(void) fputs("*bad*", stderr); |
|||
break; |
|||
} |
|||
} |
|||
(void) fprintf(stderr, ",\"%s\"]\n", m->desc); |
|||
} |
|||
#endif |
|||
|
|||
/*VARARGS*/ |
|||
protected void |
|||
file_magwarn(struct magic_set *ms, const char *f, ...) |
|||
{ |
|||
va_list va; |
|||
|
|||
/* cuz we use stdout for most, stderr here */ |
|||
(void) fflush(stdout); |
|||
|
|||
if (ms->file) |
|||
(void) fprintf(stderr, "%s, %lu: ", ms->file, |
|||
(unsigned long)ms->line); |
|||
(void) fprintf(stderr, "Warning: "); |
|||
va_start(va, f); |
|||
(void) vfprintf(stderr, f, va); |
|||
va_end(va); |
|||
(void) fputc('\n', stderr); |
|||
} |
|||
|
|||
protected const char * |
|||
file_fmttime(uint32_t v, int local) |
|||
{ |
|||
char *pp; |
|||
time_t t = (time_t)v; |
|||
struct tm *tm; |
|||
|
|||
if (local) { |
|||
pp = ctime(&t); |
|||
} else { |
|||
#ifndef HAVE_DAYLIGHT |
|||
private int daylight = 0; |
|||
#ifdef HAVE_TM_ISDST |
|||
private time_t now = (time_t)0; |
|||
|
|||
if (now == (time_t)0) { |
|||
struct tm *tm1; |
|||
(void)time(&now); |
|||
tm1 = localtime(&now); |
|||
if (tm1 == NULL) |
|||
return "*Invalid time*"; |
|||
daylight = tm1->tm_isdst; |
|||
} |
|||
#endif /* HAVE_TM_ISDST */ |
|||
#endif /* HAVE_DAYLIGHT */ |
|||
if (daylight) |
|||
t += 3600; |
|||
tm = gmtime(&t); |
|||
if (tm == NULL) |
|||
return "*Invalid time*"; |
|||
pp = asctime(tm); |
|||
} |
|||
|
|||
pp[strcspn(pp, "\n")] = '\0'; |
|||
return pp; |
|||
} |
|||
1016
ext/fileinfo/libmagic/readelf.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,236 @@ |
|||
/* |
|||
* Copyright (c) Christos Zoulas 2003. |
|||
* All Rights Reserved. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* @(#)Id: readelf.h,v 1.9 2002/05/16 18:45:56 christos Exp |
|||
* |
|||
* Provide elf data structures for non-elf machines, allowing file |
|||
* non-elf hosts to determine if an elf binary is stripped. |
|||
* Note: cobbled from the linux header file, with modifications |
|||
*/ |
|||
#ifndef __fake_elf_h__ |
|||
#define __fake_elf_h__ |
|||
|
|||
#if HAVE_STDINT_H |
|||
#include <stdint.h> |
|||
#endif |
|||
|
|||
typedef uint32_t Elf32_Addr; |
|||
typedef uint32_t Elf32_Off; |
|||
typedef uint16_t Elf32_Half; |
|||
typedef uint32_t Elf32_Word; |
|||
typedef uint8_t Elf32_Char; |
|||
|
|||
#if SIZEOF_LONG_LONG != 8 |
|||
#define USE_ARRAY_FOR_64BIT_TYPES |
|||
typedef uint32_t Elf64_Addr[2]; |
|||
typedef uint32_t Elf64_Off[2]; |
|||
typedef uint32_t Elf64_Xword[2]; |
|||
#else |
|||
#undef USE_ARRAY_FOR_64BIT_TYPES |
|||
typedef uint64_t Elf64_Addr; |
|||
typedef uint64_t Elf64_Off; |
|||
typedef uint64_t Elf64_Xword; |
|||
#endif |
|||
typedef uint16_t Elf64_Half; |
|||
typedef uint32_t Elf64_Word; |
|||
typedef uint8_t Elf64_Char; |
|||
|
|||
#define EI_NIDENT 16 |
|||
|
|||
typedef struct { |
|||
Elf32_Char e_ident[EI_NIDENT]; |
|||
Elf32_Half e_type; |
|||
Elf32_Half e_machine; |
|||
Elf32_Word e_version; |
|||
Elf32_Addr e_entry; /* Entry point */ |
|||
Elf32_Off e_phoff; |
|||
Elf32_Off e_shoff; |
|||
Elf32_Word e_flags; |
|||
Elf32_Half e_ehsize; |
|||
Elf32_Half e_phentsize; |
|||
Elf32_Half e_phnum; |
|||
Elf32_Half e_shentsize; |
|||
Elf32_Half e_shnum; |
|||
Elf32_Half e_shstrndx; |
|||
} Elf32_Ehdr; |
|||
|
|||
typedef struct { |
|||
Elf64_Char e_ident[EI_NIDENT]; |
|||
Elf64_Half e_type; |
|||
Elf64_Half e_machine; |
|||
Elf64_Word e_version; |
|||
Elf64_Addr e_entry; /* Entry point */ |
|||
Elf64_Off e_phoff; |
|||
Elf64_Off e_shoff; |
|||
Elf64_Word e_flags; |
|||
Elf64_Half e_ehsize; |
|||
Elf64_Half e_phentsize; |
|||
Elf64_Half e_phnum; |
|||
Elf64_Half e_shentsize; |
|||
Elf64_Half e_shnum; |
|||
Elf64_Half e_shstrndx; |
|||
} Elf64_Ehdr; |
|||
|
|||
/* e_type */ |
|||
#define ET_REL 1 |
|||
#define ET_EXEC 2 |
|||
#define ET_DYN 3 |
|||
#define ET_CORE 4 |
|||
|
|||
/* sh_type */ |
|||
#define SHT_SYMTAB 2 |
|||
#define SHT_NOTE 7 |
|||
#define SHT_DYNSYM 11 |
|||
|
|||
/* elf type */ |
|||
#define ELFDATANONE 0 /* e_ident[EI_DATA] */ |
|||
#define ELFDATA2LSB 1 |
|||
#define ELFDATA2MSB 2 |
|||
|
|||
/* elf class */ |
|||
#define ELFCLASSNONE 0 |
|||
#define ELFCLASS32 1 |
|||
#define ELFCLASS64 2 |
|||
|
|||
/* magic number */ |
|||
#define EI_MAG0 0 /* e_ident[] indexes */ |
|||
#define EI_MAG1 1 |
|||
#define EI_MAG2 2 |
|||
#define EI_MAG3 3 |
|||
#define EI_CLASS 4 |
|||
#define EI_DATA 5 |
|||
#define EI_VERSION 6 |
|||
#define EI_PAD 7 |
|||
|
|||
#define ELFMAG0 0x7f /* EI_MAG */ |
|||
#define ELFMAG1 'E' |
|||
#define ELFMAG2 'L' |
|||
#define ELFMAG3 'F' |
|||
#define ELFMAG "\177ELF" |
|||
|
|||
#define OLFMAG1 'O' |
|||
#define OLFMAG "\177OLF" |
|||
|
|||
typedef struct { |
|||
Elf32_Word p_type; |
|||
Elf32_Off p_offset; |
|||
Elf32_Addr p_vaddr; |
|||
Elf32_Addr p_paddr; |
|||
Elf32_Word p_filesz; |
|||
Elf32_Word p_memsz; |
|||
Elf32_Word p_flags; |
|||
Elf32_Word p_align; |
|||
} Elf32_Phdr; |
|||
|
|||
typedef struct { |
|||
Elf64_Word p_type; |
|||
Elf64_Word p_flags; |
|||
Elf64_Off p_offset; |
|||
Elf64_Addr p_vaddr; |
|||
Elf64_Addr p_paddr; |
|||
Elf64_Xword p_filesz; |
|||
Elf64_Xword p_memsz; |
|||
Elf64_Xword p_align; |
|||
} Elf64_Phdr; |
|||
|
|||
#define PT_NULL 0 /* p_type */ |
|||
#define PT_LOAD 1 |
|||
#define PT_DYNAMIC 2 |
|||
#define PT_INTERP 3 |
|||
#define PT_NOTE 4 |
|||
#define PT_SHLIB 5 |
|||
#define PT_PHDR 6 |
|||
#define PT_NUM 7 |
|||
|
|||
typedef struct { |
|||
Elf32_Word sh_name; |
|||
Elf32_Word sh_type; |
|||
Elf32_Word sh_flags; |
|||
Elf32_Addr sh_addr; |
|||
Elf32_Off sh_offset; |
|||
Elf32_Word sh_size; |
|||
Elf32_Word sh_link; |
|||
Elf32_Word sh_info; |
|||
Elf32_Word sh_addralign; |
|||
Elf32_Word sh_entsize; |
|||
} Elf32_Shdr; |
|||
|
|||
typedef struct { |
|||
Elf64_Word sh_name; |
|||
Elf64_Word sh_type; |
|||
Elf64_Off sh_flags; |
|||
Elf64_Addr sh_addr; |
|||
Elf64_Off sh_offset; |
|||
Elf64_Off sh_size; |
|||
Elf64_Word sh_link; |
|||
Elf64_Word sh_info; |
|||
Elf64_Off sh_addralign; |
|||
Elf64_Off sh_entsize; |
|||
} Elf64_Shdr; |
|||
|
|||
#define NT_NETBSD_CORE_PROCINFO 1 |
|||
|
|||
/* Note header in a PT_NOTE section */ |
|||
typedef struct elf_note { |
|||
Elf32_Word n_namesz; /* Name size */ |
|||
Elf32_Word n_descsz; /* Content size */ |
|||
Elf32_Word n_type; /* Content type */ |
|||
} Elf32_Nhdr; |
|||
|
|||
typedef struct { |
|||
Elf64_Word n_namesz; |
|||
Elf64_Word n_descsz; |
|||
Elf64_Word n_type; |
|||
} Elf64_Nhdr; |
|||
|
|||
/* Notes used in ET_CORE */ |
|||
#define NT_PRSTATUS 1 |
|||
#define NT_PRFPREG 2 |
|||
#define NT_PRPSINFO 3 |
|||
#define NT_PRXREG 4 |
|||
#define NT_TASKSTRUCT 4 |
|||
#define NT_PLATFORM 5 |
|||
#define NT_AUXV 6 |
|||
|
|||
/* Note types used in executables */ |
|||
/* NetBSD executables (name = "NetBSD") */ |
|||
#define NT_NETBSD_VERSION 1 |
|||
#define NT_NETBSD_EMULATION 2 |
|||
#define NT_FREEBSD_VERSION 1 |
|||
#define NT_OPENBSD_VERSION 1 |
|||
#define NT_DRAGONFLY_VERSION 1 |
|||
/* GNU executables (name = "GNU") */ |
|||
#define NT_GNU_VERSION 1 |
|||
|
|||
/* GNU OS tags */ |
|||
#define GNU_OS_LINUX 0 |
|||
#define GNU_OS_HURD 1 |
|||
#define GNU_OS_SOLARIS 2 |
|||
#define GNU_OS_KFREEBSD 3 |
|||
#define GNU_OS_KNETBSD 4 |
|||
|
|||
#endif |
|||
1825
ext/fileinfo/libmagic/softmagic.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,73 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* 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. |
|||
*/ |
|||
/* |
|||
* Header file for public domain tar (tape archive) program. |
|||
* |
|||
* @(#)tar.h 1.20 86/10/29 Public Domain. |
|||
* |
|||
* Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu. |
|||
* |
|||
* $File: tar.h,v 1.12 2008/02/07 00:58:52 christos Exp $ # checkin only |
|||
*/ |
|||
|
|||
/* |
|||
* Header block on tape. |
|||
* |
|||
* I'm going to use traditional DP naming conventions here. |
|||
* A "block" is a big chunk of stuff that we do I/O on. |
|||
* A "record" is a piece of info that we care about. |
|||
* Typically many "record"s fit into a "block". |
|||
*/ |
|||
#define RECORDSIZE 512 |
|||
#define NAMSIZ 100 |
|||
#define TUNMLEN 32 |
|||
#define TGNMLEN 32 |
|||
|
|||
union record { |
|||
char charptr[RECORDSIZE]; |
|||
struct header { |
|||
char name[NAMSIZ]; |
|||
char mode[8]; |
|||
char uid[8]; |
|||
char gid[8]; |
|||
char size[12]; |
|||
char mtime[12]; |
|||
char chksum[8]; |
|||
char linkflag; |
|||
char linkname[NAMSIZ]; |
|||
char magic[8]; |
|||
char uname[TUNMLEN]; |
|||
char gname[TGNMLEN]; |
|||
char devmajor[8]; |
|||
char devminor[8]; |
|||
} header; |
|||
}; |
|||
|
|||
/* The magic field is filled with this if uname and gname are valid. */ |
|||
#define TMAGIC "ustar" /* 5 chars and a null */ |
|||
#define GNUTMAGIC "ustar " /* 7 chars and a null */ |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue