diff options
Diffstat (limited to 'subversion/libsvn_subr/magic.c')
-rw-r--r-- | subversion/libsvn_subr/magic.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/subversion/libsvn_subr/magic.c b/subversion/libsvn_subr/magic.c new file mode 100644 index 0000000..812a263 --- /dev/null +++ b/subversion/libsvn_subr/magic.c @@ -0,0 +1,161 @@ +/* + * magic.c: wrappers around libmagic + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +/* ==================================================================== */ + + +/*** Includes. ***/ + +#include <apr_lib.h> +#include <apr_file_info.h> + +#include "svn_io.h" +#include "svn_types.h" +#include "svn_pools.h" +#include "svn_error.h" + +#include "svn_private_config.h" + +#include "private/svn_magic.h" + +#ifdef SVN_HAVE_LIBMAGIC +#include <magic.h> +#endif + +struct svn_magic__cookie_t { +#ifdef SVN_HAVE_LIBMAGIC + magic_t magic; +#else + char dummy; +#endif +}; + +#ifdef SVN_HAVE_LIBMAGIC +/* Close the magic database. */ +static apr_status_t +close_magic_cookie(void *baton) +{ + svn_magic__cookie_t *mc = (svn_magic__cookie_t*)baton; + magic_close(mc->magic); + return APR_SUCCESS; +} +#endif + +void +svn_magic__init(svn_magic__cookie_t **magic_cookie, + apr_pool_t *result_pool) +{ + + svn_magic__cookie_t *mc = NULL; + +#ifdef SVN_HAVE_LIBMAGIC + mc = apr_palloc(result_pool, sizeof(*mc)); + + /* Initialise libmagic. */ +#ifndef MAGIC_MIME_TYPE + /* Some old versions of libmagic don't support MAGIC_MIME_TYPE. + * We can use MAGIC_MIME instead. It returns more than we need + * but we can work around that (see below). */ + mc->magic = magic_open(MAGIC_MIME | MAGIC_ERROR); +#else + mc->magic = magic_open(MAGIC_MIME_TYPE | MAGIC_ERROR); +#endif + if (mc->magic) + { + /* This loads the default magic database. + * Point the MAGIC environment variable at your favourite .mgc + * file to load a non-default database. */ + if (magic_load(mc->magic, NULL) == -1) + { + magic_close(mc->magic); + mc = NULL; + } + else + apr_pool_cleanup_register(result_pool, mc, close_magic_cookie, + apr_pool_cleanup_null); + } +#endif + + *magic_cookie = mc; +} + +svn_error_t * +svn_magic__detect_binary_mimetype(const char **mimetype, + const char *local_abspath, + svn_magic__cookie_t *magic_cookie, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *magic_mimetype = NULL; +#ifdef SVN_HAVE_LIBMAGIC + apr_finfo_t finfo; + + /* Do not ask libmagic for the mime-types of empty files. + * This prevents mime-types like "application/x-empty" from making + * Subversion treat empty files as binary. */ + SVN_ERR(svn_io_stat(&finfo, local_abspath, APR_FINFO_SIZE, scratch_pool)); + if (finfo.size > 0) + { + magic_mimetype = magic_file(magic_cookie->magic, local_abspath); + if (magic_mimetype) + { + /* Only return binary mime-types. */ + if (strncmp(magic_mimetype, "text/", 5) == 0) + magic_mimetype = NULL; + else + { + svn_error_t *err; +#ifndef MAGIC_MIME_TYPE + char *p; + + /* Strip off trailing stuff like " charset=ascii". */ + p = strchr(magic_mimetype, ' '); + if (p) + *p = '\0'; +#endif + /* Make sure we got a valid mime type. */ + err = svn_mime_type_validate(magic_mimetype, scratch_pool); + if (err) + { + if (err->apr_err == SVN_ERR_BAD_MIME_TYPE) + { + svn_error_clear(err); + magic_mimetype = NULL; + } + else + return svn_error_trace(err); + } + else + { + /* The string is allocated from memory managed by libmagic + * so we must copy it to the result pool. */ + magic_mimetype = apr_pstrdup(result_pool, magic_mimetype); + } + } + } + } +#endif + + *mimetype = magic_mimetype; + return SVN_NO_ERROR; +} |