mirror of
https://github.com/php/php-src.git
synced 2024-11-30 21:35:36 +08:00
- use php's stream in libmagic
- remove duplicate code (like mime_content_type() compatibility function now use the same base as finfo_file()) - make it portable (works now on windows too, belongs other OSes) - ([20:28] <lsmith> Pierre: ok please commit)
This commit is contained in:
parent
0f701b8d31
commit
99041160df
@ -38,6 +38,10 @@
|
||||
#include "php_fileinfo.h"
|
||||
#include "fopen_wrappers.h" /* needed for is_url */
|
||||
|
||||
#ifndef _S_IFDIR
|
||||
# define _S_IFDIR S_IFDIR
|
||||
#endif
|
||||
|
||||
/* {{{ macros and type definitions */
|
||||
struct php_fileinfo {
|
||||
long options;
|
||||
@ -405,83 +409,148 @@ PHP_FUNCTION(finfo_set_flags)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
|
||||
#define FILEINFO_MODE_BUFFER 0
|
||||
#define FILEINFO_MODE_STREAM 1
|
||||
#define FILEINFO_MODE_FILE 2
|
||||
|
||||
static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mimetype_emu) /* {{{ */
|
||||
{
|
||||
long options = 0;
|
||||
char *tmp, *ret_val, *buffer = NULL;
|
||||
char *ret_val = NULL, *buffer = NULL;
|
||||
int buffer_len;
|
||||
struct php_fileinfo *finfo;
|
||||
zval *zfinfo, *zcontext = NULL;
|
||||
zval *what;
|
||||
char mime_directory[] = "directory";
|
||||
|
||||
struct magic_set *magic = NULL;
|
||||
FILEINFO_DECLARE_INIT_OBJECT(object)
|
||||
|
||||
if (object) {
|
||||
if (mimetype_emu) {
|
||||
|
||||
/* mime_content_type(..) emulation */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &what) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Z_TYPE_P(what)) {
|
||||
case IS_STRING:
|
||||
buffer = Z_STRVAL_P(what);
|
||||
buffer_len = Z_STRLEN_P(what);
|
||||
break;
|
||||
|
||||
case IS_RESOURCE:
|
||||
mode = FILEINFO_MODE_STREAM;
|
||||
break;
|
||||
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
magic = magic_open(MAGIC_MIME);
|
||||
if (magic_load(magic, NULL) == -1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database.");
|
||||
magic_close(magic);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
} else if (object) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &buffer, &buffer_len, &options, &zcontext) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
FILEINFO_FROM_OBJECT(finfo, object);
|
||||
magic = finfo->magic;
|
||||
} else {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lr", &zfinfo, &buffer, &buffer_len, &options, &zcontext) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo);
|
||||
magic = finfo->magic;
|
||||
}
|
||||
|
||||
/* Set options for the current file/buffer. */
|
||||
if (options) {
|
||||
FINFO_SET_OPTION(finfo->magic, options)
|
||||
FINFO_SET_OPTION(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) {
|
||||
switch (mode) {
|
||||
case FILEINFO_MODE_BUFFER:
|
||||
{
|
||||
ret_val = (char *) magic_buffer(magic, buffer, buffer_len);
|
||||
break;
|
||||
}
|
||||
|
||||
case FILEINFO_MODE_STREAM:
|
||||
{
|
||||
php_stream *stream;
|
||||
off_t streampos;
|
||||
|
||||
php_stream_from_zval_no_verify(stream, &what);
|
||||
if (!stream) {
|
||||
goto common;
|
||||
}
|
||||
|
||||
streampos = php_stream_tell(stream); /* remember stream position for restoration */
|
||||
php_stream_seek(stream, 0, SEEK_SET);
|
||||
|
||||
ret_val = (char *) magic_stream(magic, stream);
|
||||
break;
|
||||
}
|
||||
|
||||
case FILEINFO_MODE_FILE:
|
||||
{
|
||||
/* determine if the file is a local file or remote URL */
|
||||
char *tmp2;
|
||||
php_stream_wrapper *wrap;
|
||||
struct stat sb;
|
||||
|
||||
if (buffer_len < 1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty filename or path");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
buffer_len = php_stream_copy_to_mem(stream, &tmp, HOWMANY, 0);
|
||||
php_stream_close(stream);
|
||||
|
||||
if (buffer_len == 0) {
|
||||
RETURN_FALSE;
|
||||
if (php_sys_stat(buffer, &sb) == 0 && (sb.st_mode & _S_IFDIR)) {
|
||||
ret_val = mime_directory;
|
||||
goto common;
|
||||
}
|
||||
} else { /* local file */
|
||||
char resolved_path[MAXPATHLEN];
|
||||
|
||||
if (*buffer && VCWD_REALPATH(buffer, resolved_path)) {
|
||||
if ((PG(safe_mode) && (!php_checkuid(resolved_path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(resolved_path TSRMLS_CC)) {
|
||||
wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0 TSRMLS_CC);
|
||||
|
||||
if (wrap) {
|
||||
php_stream_context *context = php_stream_context_from_zval(zcontext, 0);
|
||||
|
||||
php_stream *stream = php_stream_open_wrapper_ex(buffer, "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
|
||||
|
||||
if (!stream) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
ret_val = (char *) magic_file(finfo->magic, resolved_path);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
|
||||
ret_val = magic_stream(magic, stream);
|
||||
php_stream_close(stream);
|
||||
}
|
||||
goto common;
|
||||
break;
|
||||
}
|
||||
} else { /* buffer */
|
||||
tmp = buffer;
|
||||
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ret_val = (char *) magic_buffer(finfo->magic, tmp, buffer_len);
|
||||
if (mode) {
|
||||
efree(tmp);
|
||||
}
|
||||
common:
|
||||
if (mimetype_emu) {
|
||||
if (magic) {
|
||||
magic_close(magic);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore options */
|
||||
if (options) {
|
||||
FINFO_SET_OPTION(finfo->magic, finfo->options)
|
||||
FINFO_SET_OPTION(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));
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic));
|
||||
RETURN_FALSE;
|
||||
} else {
|
||||
RETURN_STRING(ret_val, 1);
|
||||
@ -493,7 +562,7 @@ common:
|
||||
Return information about a file. */
|
||||
PHP_FUNCTION(finfo_file)
|
||||
{
|
||||
_php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
||||
_php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_FILE, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -501,7 +570,7 @@ PHP_FUNCTION(finfo_file)
|
||||
Return infromation about a string buffer. */
|
||||
PHP_FUNCTION(finfo_buffer)
|
||||
{
|
||||
_php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
||||
_php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_BUFFER, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -509,90 +578,7 @@ PHP_FUNCTION(finfo_buffer)
|
||||
Return content-type for file */
|
||||
PHP_FUNCTION(mime_content_type)
|
||||
{
|
||||
zval *what;
|
||||
magic_t magic;
|
||||
char *tmp, *ret_val;
|
||||
int buffer_len;
|
||||
char *tmp2;
|
||||
php_stream_wrapper *wrap;
|
||||
zval *zcontext = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &what) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETVAL_FALSE;
|
||||
|
||||
magic = magic_open(MAGIC_MIME);
|
||||
if (magic_load(magic, NULL) == -1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
switch (Z_TYPE_P(what)) {
|
||||
case IS_STRING:
|
||||
wrap = php_stream_locate_url_wrapper(Z_STRVAL_P(what), &tmp2, 0 TSRMLS_CC);
|
||||
/* determine if the file is a local file or remote URL */
|
||||
if (wrap && wrap->is_url) {
|
||||
php_stream_context *context = php_stream_context_from_zval(zcontext, 0);
|
||||
php_stream *stream = php_stream_open_wrapper_ex(Z_STRVAL_P(what), "rb",
|
||||
ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
|
||||
if (!stream) {
|
||||
goto cleanup;
|
||||
}
|
||||
buffer_len = php_stream_copy_to_mem(stream, &tmp, 4096, 0);
|
||||
php_stream_close(stream);
|
||||
|
||||
if (buffer_len == 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
ret_val = (char *) magic_buffer(magic, tmp, buffer_len);
|
||||
} else { /* local file */
|
||||
char resolved_path[MAXPATHLEN];
|
||||
|
||||
if (*Z_STRVAL_P(what) && VCWD_REALPATH(Z_STRVAL_P(what), resolved_path)) {
|
||||
if ((PG(safe_mode) && (!php_checkuid(resolved_path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(resolved_path TSRMLS_CC)) {
|
||||
goto cleanup;
|
||||
}
|
||||
ret_val = (char *) magic_file(magic, resolved_path);
|
||||
} else {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IS_RESOURCE:
|
||||
{
|
||||
php_stream *stream;
|
||||
off_t streampos;
|
||||
|
||||
php_stream_from_zval_no_verify(stream, &what);
|
||||
if (!stream) {
|
||||
goto cleanup;
|
||||
}
|
||||
streampos = php_stream_tell(stream); /* remember stream position for restoration */
|
||||
php_stream_seek(stream, 0, SEEK_SET);
|
||||
|
||||
buffer_len = php_stream_copy_to_mem(stream, &tmp, 4096, 0);
|
||||
php_stream_seek(stream, streampos, SEEK_SET);
|
||||
|
||||
if (buffer_len == 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
ret_val = (char *) magic_buffer(magic, tmp, buffer_len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments");
|
||||
goto cleanup;
|
||||
}
|
||||
if (!ret_val) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s",
|
||||
magic_errno(magic), magic_error(magic));
|
||||
} else {
|
||||
RETVAL_STRING(ret_val, 1);
|
||||
}
|
||||
cleanup:
|
||||
magic_close(magic);
|
||||
_php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -29,21 +29,32 @@
|
||||
* apprentice - make one pass through /etc/magic, learning its secrets.
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
|
||||
#include "file.h"
|
||||
#include "magic.h"
|
||||
#include "patchlevel.h"
|
||||
#include <stdlib.h>
|
||||
//#ifdef HAVE_UNISTD_H
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#include "win32/unistd.h"
|
||||
#define strtoull _strtoui64
|
||||
#else
|
||||
#include <unistd.h>
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef PHP_WIN32
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifndef PHP_WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
FILE_RCSID("@(#)$File: apprentice.c,v 1.132 2008/03/28 18:19:30 christos Exp $")
|
||||
@ -174,6 +185,10 @@ static const struct type_tbl_s {
|
||||
# undef XX_NULL
|
||||
};
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
|
||||
#endif
|
||||
|
||||
private int
|
||||
get_type(const char *l, const char **t)
|
||||
{
|
||||
@ -528,30 +543,43 @@ private void
|
||||
load_1(struct magic_set *ms, int action, const char *fn, int *errs,
|
||||
struct magic_entry **marray, uint32_t *marraycount)
|
||||
{
|
||||
char line[BUFSIZ];
|
||||
char buffer[BUFSIZ + 1];
|
||||
char *line;
|
||||
size_t line_len;
|
||||
size_t lineno = 0;
|
||||
FILE *f = fopen(ms->file = fn, "r");
|
||||
if (f == NULL) {
|
||||
|
||||
php_stream *stream;
|
||||
|
||||
TSRMLS_FETCH();
|
||||
|
||||
#if (PHP_MAJOR_VERSION < 6)
|
||||
stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
|
||||
#else
|
||||
stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
|
||||
#endif
|
||||
|
||||
if (stream == NULL) {
|
||||
if (errno != ENOENT)
|
||||
file_error(ms, errno, "cannot read magic file `%s'",
|
||||
fn);
|
||||
(*errs)++;
|
||||
} else {
|
||||
|
||||
/* read and parse this file */
|
||||
for (ms->line = 1; fgets(line, sizeof(line), f) != NULL; ms->line++) {
|
||||
size_t len;
|
||||
len = strlen(line);
|
||||
if (len == 0) /* null line, garbage, etc */
|
||||
for (ms->line = 1; (line = php_stream_get_line(stream, buffer , BUFSIZ, &line_len)) != NULL; ms->line++) {
|
||||
if (line_len == 0 || /* null line, garbage, etc */
|
||||
line[0] == '\0' || /* empty*/
|
||||
line[0] == '#' || /* comment */
|
||||
line[0] == '\n' || line[0] == '\r') { /* New Line */
|
||||
continue;
|
||||
if (line[len - 1] == '\n') {
|
||||
lineno++;
|
||||
line[len - 1] = '\0'; /* delete newline */
|
||||
}
|
||||
if (line[0] == '\0') /* empty, do not parse */
|
||||
continue;
|
||||
if (line[0] == '#') /* comment, do not parse */
|
||||
continue;
|
||||
if (len > mime_marker_len &&
|
||||
|
||||
if (line[line_len - 1] == '\n') {
|
||||
lineno++;
|
||||
line[line_len - 1] = '\0'; /* delete newline */
|
||||
}
|
||||
|
||||
if (line_len > mime_marker_len &&
|
||||
memcmp(line, mime_marker, mime_marker_len) == 0) {
|
||||
/* MIME type */
|
||||
if (parse_mime(ms, marray, marraycount,
|
||||
@ -563,7 +591,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
|
||||
(*errs)++;
|
||||
}
|
||||
|
||||
(void)fclose(f);
|
||||
php_stream_close(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +613,7 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
|
||||
|
||||
ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */
|
||||
|
||||
maxmagic = MAXMAGIS;
|
||||
maxmagic = MAXMAGIS;
|
||||
marray = ecalloc(maxmagic, sizeof(*marray));
|
||||
marraycount = 0;
|
||||
|
||||
@ -594,7 +622,7 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
|
||||
(void)fprintf(stderr, "%s\n", usg_hdr);
|
||||
|
||||
/* load directory or file */
|
||||
if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
if (php_sys_stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
dir = opendir(fn);
|
||||
if (dir) {
|
||||
while ((d = readdir(dir))) {
|
||||
@ -1816,17 +1844,20 @@ private int
|
||||
apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
|
||||
const char *fn)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
uint32_t *ptr;
|
||||
uint32_t version;
|
||||
int needsbyteswap;
|
||||
char *dbname = NULL;
|
||||
void *mm = NULL;
|
||||
int ret = 0;
|
||||
php_stream *stream;
|
||||
php_stream_statbuf st;
|
||||
|
||||
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (fn == NULL) {
|
||||
mm = &php_magic_database;
|
||||
mm = (void *)&php_magic_database;
|
||||
ret = 3;
|
||||
goto internal_loaded;
|
||||
}
|
||||
@ -1835,27 +1866,34 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
|
||||
if (dbname == NULL)
|
||||
goto error2;
|
||||
|
||||
if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1)
|
||||
goto error2;
|
||||
#if (PHP_MAJOR_VERSION < 6)
|
||||
stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
|
||||
#else
|
||||
stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
|
||||
#endif
|
||||
|
||||
if (fstat(fd, &st) == -1) {
|
||||
if (!stream) {
|
||||
goto error2;
|
||||
}
|
||||
|
||||
if (php_stream_stat(stream, &st) < 0) {
|
||||
file_error(ms, errno, "cannot stat `%s'", dbname);
|
||||
goto error1;
|
||||
}
|
||||
if (st.st_size < 8) {
|
||||
|
||||
if (st.sb.st_size < 8) {
|
||||
file_error(ms, 0, "file `%s' is too small", dbname);
|
||||
goto error1;
|
||||
}
|
||||
|
||||
mm = emalloc((size_t)st.st_size);
|
||||
if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
|
||||
mm = emalloc((size_t)st.sb.st_size);
|
||||
if (php_stream_read(stream, mm, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
|
||||
file_badread(ms);
|
||||
goto error1;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
(void)close(fd);
|
||||
fd = -1;
|
||||
php_stream_close(stream);
|
||||
|
||||
internal_loaded:
|
||||
*magicp = mm;
|
||||
@ -1882,7 +1920,7 @@ internal_loaded:
|
||||
if (fn == NULL) {
|
||||
*nmagicp = (sizeof(php_magic_database) / sizeof(struct magic));
|
||||
} else {
|
||||
*nmagicp = (uint32_t)(st.st_size / sizeof(struct magic));
|
||||
*nmagicp = (uint32_t)(st.sb.st_size / sizeof(struct magic));
|
||||
}
|
||||
if (*nmagicp > 0) {
|
||||
(*nmagicp)--;
|
||||
@ -1898,8 +1936,9 @@ internal_loaded:
|
||||
return ret;
|
||||
|
||||
error1:
|
||||
if (fd != -1)
|
||||
(void)close(fd);
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
}
|
||||
if (mm) {
|
||||
efree(mm);
|
||||
} else {
|
||||
@ -1921,38 +1960,47 @@ private int
|
||||
apprentice_compile(struct magic_set *ms, struct magic **magicp,
|
||||
uint32_t *nmagicp, const char *fn)
|
||||
{
|
||||
int fd;
|
||||
char *dbname;
|
||||
int rv = -1;
|
||||
php_stream *stream;
|
||||
|
||||
TSRMLS_FETCH();
|
||||
|
||||
mkdbname(fn, &dbname, 1);
|
||||
|
||||
if (dbname == NULL)
|
||||
if (dbname == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) {
|
||||
/* wb+ == O_WRONLY|O_CREAT|O_TRUNC|O_BINARY */
|
||||
#if (PHP_MAJOR_VERSION < 6)
|
||||
stream = php_stream_open_wrapper((char *)fn, "wb+", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
|
||||
#else
|
||||
stream = php_stream_open_wrapper((char *)fn, "wb+", REPORT_ERRORS, NULL);
|
||||
#endif
|
||||
|
||||
if (!stream) {
|
||||
file_error(ms, errno, "cannot open `%s'", dbname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
|
||||
if (php_stream_write(stream, (char *)ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
|
||||
file_error(ms, errno, "error writing `%s'", dbname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lseek(fd, (off_t)sizeof(struct magic), SEEK_SET)
|
||||
!= sizeof(struct magic)) {
|
||||
if (php_stream_seek(stream,(off_t)sizeof(struct magic), SEEK_SET) != sizeof(struct magic)) {
|
||||
file_error(ms, errno, "error seeking `%s'", dbname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write(fd, *magicp, (sizeof(struct magic) * *nmagicp))
|
||||
!= (ssize_t)(sizeof(struct magic) * *nmagicp)) {
|
||||
if (php_stream_write(stream, (char *)*magicp, (sizeof(struct magic) * *nmagicp) != (ssize_t)(sizeof(struct magic) * *nmagicp))) {
|
||||
file_error(ms, errno, "error writing `%s'", dbname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void)close(fd);
|
||||
php_stream_close(stream);
|
||||
|
||||
rv = 0;
|
||||
out:
|
||||
efree(dbname);
|
||||
|
@ -32,6 +32,7 @@
|
||||
* uncompress(method, old, n, newch) - uncompress old into new,
|
||||
* using method, return sizeof new
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "file.h"
|
||||
#include "magic.h"
|
||||
@ -43,7 +44,9 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef PHP_WIN32
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
@ -55,6 +58,7 @@
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#undef FIONREAD
|
||||
|
||||
#ifndef lint
|
||||
FILE_RCSID("@(#)$File: compress.c,v 1.56 2008/02/07 00:58:52 christos Exp $")
|
||||
@ -86,6 +90,7 @@ private size_t ncompr = sizeof(compr) / sizeof(compr[0]);
|
||||
|
||||
|
||||
private ssize_t swrite(int, const void *, size_t);
|
||||
#ifdef PHP_FILEINFO_UNCOMPRESS
|
||||
private size_t uncompressbuf(struct magic_set *, int, size_t,
|
||||
const unsigned char *, unsigned char **, size_t);
|
||||
#ifdef BUILTIN_DECOMPRESS
|
||||
@ -138,6 +143,7 @@ error:
|
||||
ms->flags |= MAGIC_COMPRESS;
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* `safe' write for sockets and pipes.
|
||||
@ -295,6 +301,7 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
|
||||
return fd;
|
||||
}
|
||||
|
||||
#ifdef PHP_FILEINFO_UNCOMPRESS
|
||||
#ifdef BUILTIN_DECOMPRESS
|
||||
|
||||
#define FHCRC (1 << 1)
|
||||
@ -365,6 +372,7 @@ uncompressgzipped(struct magic_set *ms, const unsigned char *old,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
private size_t
|
||||
uncompressbuf(struct magic_set *ms, int fd, size_t method,
|
||||
const unsigned char *old, unsigned char **newch, size_t n)
|
||||
@ -483,3 +491,4 @@ err:
|
||||
return n;
|
||||
}
|
||||
}
|
||||
#endif /* if PHP_FILEINFO_UNCOMPRESS */
|
||||
|
@ -33,9 +33,7 @@
|
||||
#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>
|
||||
@ -46,6 +44,9 @@
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#ifdef PHP_WIN32
|
||||
#include "win32/php_stdint.h"
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "ext/standard/php_string.h"
|
||||
@ -62,7 +63,7 @@
|
||||
#define MAGIC "/etc/magic"
|
||||
#endif
|
||||
|
||||
#ifdef __EMX__
|
||||
#if defined(__EMX__) || defined(PHP_WIN32)
|
||||
#define PATHSEP ';'
|
||||
#else
|
||||
#define PATHSEP ':'
|
||||
@ -323,16 +324,18 @@ 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 *,
|
||||
protected int file_buffer(struct magic_set *, php_stream *, const char *, const void *,
|
||||
size_t);
|
||||
protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
|
||||
protected int file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream);
|
||||
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);
|
||||
#ifdef PHP_FILEINFO_UNCOMPRESS
|
||||
protected int file_zmagic(struct magic_set *, int, const char *,
|
||||
const unsigned char *, size_t);
|
||||
#endif
|
||||
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);
|
||||
|
@ -60,69 +60,64 @@
|
||||
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;
|
||||
}
|
||||
#ifdef PHP_WIN32
|
||||
|
||||
# undef S_IFIFO
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(mode) ((mode) & _S_IFREG)
|
||||
#endif
|
||||
|
||||
protected int
|
||||
file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
|
||||
file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream)
|
||||
{
|
||||
int ret = 0;
|
||||
int mime = ms->flags & MAGIC_MIME;
|
||||
#ifdef S_IFLNK
|
||||
char buf[BUFSIZ+4];
|
||||
int nch;
|
||||
struct stat tstatbuf;
|
||||
#endif
|
||||
TSRMLS_FETCH();
|
||||
|
||||
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 (!fn && !stream) {
|
||||
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;
|
||||
if (stream) {
|
||||
php_stream_statbuf ssb;
|
||||
if (php_stream_stat(stream, &ssb) < 0) {
|
||||
if (ms->flags & MAGIC_ERROR) {
|
||||
file_error(ms, errno, "cannot stat `%s'", fn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
memcpy(sb, &ssb.sb, sizeof(struct stat));
|
||||
} else {
|
||||
if (php_sys_stat(fn, sb) != 0) {
|
||||
if (ms->flags & MAGIC_ERROR) {
|
||||
file_error(ms, errno, "cannot stat `%s'", fn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (mime) {
|
||||
if (!S_ISREG(sb->st_mode)) {
|
||||
if ((mime & MAGIC_MIME_TYPE) &&
|
||||
file_printf(ms, "application/x-not-regular-file") == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (S_ISDIR(sb->st_mode)) {
|
||||
if (file_printf(ms, "directory") == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
#ifdef S_ISUID
|
||||
if (sb->st_mode & S_ISUID)
|
||||
if (file_printf(ms, "setuid ") == -1)
|
||||
@ -139,65 +134,41 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
|
||||
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;
|
||||
#ifndef PHP_WIN32
|
||||
# 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
|
||||
#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)
|
||||
@ -212,67 +183,17 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
|
||||
return -1;
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#ifdef S_IFLNK
|
||||
case S_IFLNK:
|
||||
if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
|
||||
/* stat is used, if it made here then the link is broken */
|
||||
if (ms->flags & MAGIC_ERROR) {
|
||||
file_error(ms, errno, "unreadable symlink `%s'",
|
||||
fn);
|
||||
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:
|
||||
@ -281,12 +202,14 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
|
||||
return 1;
|
||||
#endif
|
||||
#endif
|
||||
case S_IFREG:
|
||||
break;
|
||||
default:
|
||||
file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
|
||||
return -1;
|
||||
/*NOTREACHED*/
|
||||
|
||||
case S_IFREG:
|
||||
break;
|
||||
|
||||
default:
|
||||
file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
|
||||
return -1;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -146,7 +146,7 @@ file_badread(struct magic_set *ms)
|
||||
}
|
||||
|
||||
protected int
|
||||
file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf,
|
||||
file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
|
||||
size_t nb)
|
||||
{
|
||||
int m;
|
||||
@ -166,7 +166,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __EMX__
|
||||
#if defined(__EMX__)
|
||||
if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
|
||||
switch (file_os2_apptype(ms, inname, buf, nb)) {
|
||||
case -1:
|
||||
@ -179,31 +179,30 @@ file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PHP_FILEINFO_UNCOMPRESS
|
||||
/* try compression stuff */
|
||||
if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) != 0 ||
|
||||
(m = file_zmagic(ms, fd, inname, buf, nb)) == 0) {
|
||||
/* Check if we have a tar file */
|
||||
if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 ||
|
||||
(m = file_is_tar(ms, buf, nb)) == 0) {
|
||||
/* try tests in /etc/magic (or surrogate magic file) */
|
||||
if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 ||
|
||||
(m = file_softmagic(ms, buf, nb, BINTEST)) == 0) {
|
||||
/* try known keywords, check whether it is ASCII */
|
||||
if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 ||
|
||||
(m = file_ascmagic(ms, buf, nb)) == 0) {
|
||||
/* abandon hope, all ye who remain here */
|
||||
if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
|
||||
file_printf(ms, mime ? "application/octet-stream" :
|
||||
"data") == -1)
|
||||
return -1;
|
||||
m = 1;
|
||||
}
|
||||
(m = file_zmagic(ms, stream, inname, buf, nb)) == 0)
|
||||
#endif
|
||||
{
|
||||
/* Check if we have a tar file */
|
||||
if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 || (m = file_is_tar(ms, buf, nb)) == 0) {
|
||||
/* try tests in /etc/magic (or surrogate magic file) */
|
||||
if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 || (m = file_softmagic(ms, buf, nb, BINTEST)) == 0) {
|
||||
/* try known keywords, check whether it is ASCII */
|
||||
if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 || (m = file_ascmagic(ms, buf, nb)) == 0) {
|
||||
/* abandon hope, all ye who remain here */
|
||||
if ((!mime || (mime & MAGIC_MIME_TYPE)) && file_printf(ms, mime ? "application/octet-stream" : "data") == -1) {
|
||||
return -1;
|
||||
}
|
||||
m = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BUILTIN_ELF
|
||||
if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
|
||||
nb > 5 && fd != -1) {
|
||||
if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && nb > 5 && fd != -1) {
|
||||
/*
|
||||
* We matched something in the file, so this *might*
|
||||
* be an ELF file, and the file is at least 5 bytes
|
||||
@ -212,7 +211,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf,
|
||||
* information from the ELF headers that cannot easily
|
||||
* be extracted with rules in the magic file.
|
||||
*/
|
||||
(void)file_tryelf(ms, fd, buf, nb);
|
||||
(void)file_tryelf(ms, stream, buf, nb);
|
||||
}
|
||||
#endif
|
||||
return m;
|
||||
|
@ -30,10 +30,19 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef PHP_WIN32
|
||||
#include "win32/unistd.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h> /* for MAXPATHLEN */
|
||||
#ifdef PHP_WIN32
|
||||
# include "config.w32.h"
|
||||
#else
|
||||
# include "php_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h> /* for PIPE_BUF */
|
||||
|
||||
@ -54,9 +63,9 @@
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#include <netinet/in.h> /* for byte swapping */
|
||||
|
||||
#ifndef PHP_WIN32
|
||||
# include <netinet/in.h> /* for byte swapping */
|
||||
#endif
|
||||
#include "patchlevel.h"
|
||||
|
||||
#ifndef lint
|
||||
@ -72,6 +81,11 @@ FILE_RCSID("@(#)$File: magic.c,v 1.50 2008/02/19 00:58:59 rrt Exp $")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# undef S_IFLNK
|
||||
# undef S_IFIFO
|
||||
#endif
|
||||
|
||||
#ifdef __EMX__
|
||||
private char *apptypeName = NULL;
|
||||
protected int file_os2_apptype(struct magic_set *ms, const char *fn,
|
||||
@ -82,7 +96,7 @@ 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);
|
||||
private const char *file_or_fd(struct magic_set *, const char *, int);
|
||||
private const char *file_or_stream(struct magic_set *, const char *, php_stream *);
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
@ -204,10 +218,6 @@ 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.
|
||||
@ -240,7 +250,7 @@ close_and_restore(const struct magic_set *ms, const char *name, int fd,
|
||||
public const char *
|
||||
magic_descriptor(struct magic_set *ms, int fd)
|
||||
{
|
||||
return file_or_fd(ms, NULL, fd);
|
||||
return file_or_stream(ms, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -249,17 +259,28 @@ magic_descriptor(struct magic_set *ms, int fd)
|
||||
public const char *
|
||||
magic_file(struct magic_set *ms, const char *inname)
|
||||
{
|
||||
return file_or_fd(ms, inname, STDIN_FILENO);
|
||||
return file_or_stream(ms, inname, NULL);
|
||||
}
|
||||
|
||||
public const char *
|
||||
magic_stream(struct magic_set *ms, php_stream *stream)
|
||||
{
|
||||
return file_or_stream(ms, NULL, stream);
|
||||
}
|
||||
|
||||
private const char *
|
||||
file_or_fd(struct magic_set *ms, const char *inname, int fd)
|
||||
file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
|
||||
{
|
||||
int rv = -1;
|
||||
unsigned char *buf;
|
||||
struct stat sb;
|
||||
ssize_t nbytes = 0; /* number of bytes read from a datafile */
|
||||
int ispipe = 0;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (!inname && !stream) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* one extra for terminating '\0', and
|
||||
@ -268,89 +289,65 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
|
||||
#define SLOP (1 + sizeof(union VALUETYPE))
|
||||
buf = emalloc(HOWMANY + SLOP);
|
||||
|
||||
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;
|
||||
if (file_reset(ms) == -1) {
|
||||
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;
|
||||
}
|
||||
switch (file_fsmagic(ms, inname, &sb, stream)) {
|
||||
case -1: /* error */
|
||||
goto done;
|
||||
case 0: /* nothing found */
|
||||
break;
|
||||
default: /* matched it and printed type */
|
||||
rv = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if (!stream && inname) {
|
||||
#if (PHP_MAJOR_VERSION < 6)
|
||||
stream = php_stream_open_wrapper(inname, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
|
||||
#else
|
||||
stream = php_stream_open_wrapper(inname, "rb", REPORT_ERRORS, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!stream) {
|
||||
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);
|
||||
}
|
||||
/* we should be already be in non blocking mode for network socket
|
||||
* leaving the comment/#ifdef as documentation
|
||||
*/
|
||||
#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;
|
||||
}
|
||||
if ((nbytes = php_stream_read(stream, (char *)buf, HOWMANY)) < 0) {
|
||||
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)
|
||||
if (file_buffer(ms, stream, inname, buf, (size_t)nbytes) == -1)
|
||||
goto done;
|
||||
rv = 0;
|
||||
done:
|
||||
efree(buf);
|
||||
close_and_restore(ms, inname, fd, &sb);
|
||||
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
}
|
||||
|
||||
close_and_restore(ms, inname, 0, &sb);
|
||||
return rv == 0 ? file_getbuffer(ms) : NULL;
|
||||
}
|
||||
|
||||
@ -364,7 +361,7 @@ magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
|
||||
* 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) {
|
||||
if (file_buffer(ms, NULL, NULL, buf, nb) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return file_getbuffer(ms);
|
||||
|
@ -64,6 +64,7 @@ magic_t magic_open(int);
|
||||
void magic_close(magic_t);
|
||||
|
||||
const char *magic_file(magic_t, const char *);
|
||||
const char *magic_stream(magic_t, php_stream *);
|
||||
const char *magic_descriptor(magic_t, int);
|
||||
const char *magic_buffer(magic_t, const void *, size_t);
|
||||
|
||||
|
@ -943,7 +943,6 @@ dophn_exec(struct magic_set *ms, int class, int swap, int fd, off_t off,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
protected int
|
||||
file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
|
||||
size_t nbytes)
|
||||
@ -963,6 +962,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
|
||||
|
||||
if (ms->flags & MAGIC_MIME)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* ELF executables have multiple section headers in arbitrary
|
||||
* file locations and thus file(1) cannot determine it from easily.
|
||||
|
@ -11,9 +11,15 @@ var_dump(finfo_file($fp, '.'));
|
||||
var_dump(finfo_file($fp, '&'));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
bool(false)
|
||||
|
||||
Warning: finfo_file(): Empty filename or path in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: finfo_file(): Empty filename or path in %s on line %d
|
||||
bool(false)
|
||||
string(9) "directory"
|
||||
|
||||
Warning: finfo_file(&): failed to open stream: No such file or directory in %s on line %d
|
||||
bool(false)
|
||||
|
Loading…
Reference in New Issue
Block a user