2 * magic.c: wrappers around libmagic
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
24 /* ==================================================================== */
30 #include <apr_file_info.h>
33 #include "svn_types.h"
34 #include "svn_pools.h"
35 #include "svn_error.h"
36 #include "svn_config.h"
39 #include "svn_private_config.h"
41 #include "private/svn_magic.h"
43 #ifdef SVN_HAVE_LIBMAGIC
47 struct svn_magic__cookie_t {
48 #ifdef SVN_HAVE_LIBMAGIC
55 #ifdef SVN_HAVE_LIBMAGIC
56 /* Close the magic database. */
58 close_magic_cookie(void *baton)
60 svn_magic__cookie_t *mc = (svn_magic__cookie_t*)baton;
61 magic_close(mc->magic);
67 svn_magic__init(svn_magic__cookie_t **magic_cookie,
69 apr_pool_t *result_pool)
71 svn_magic__cookie_t *mc = NULL;
73 #ifdef SVN_HAVE_LIBMAGIC
77 svn_config_t *cfg = svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG);
79 SVN_ERR(svn_config_get_bool(cfg, &enable,
80 SVN_CONFIG_SECTION_MISCELLANY,
81 SVN_CONFIG_OPTION_ENABLE_MAGIC_FILE,
90 mc = apr_palloc(result_pool, sizeof(*mc));
92 /* Initialise libmagic. */
93 #ifndef MAGIC_MIME_TYPE
94 /* Some old versions of libmagic don't support MAGIC_MIME_TYPE.
95 * We can use MAGIC_MIME instead. It returns more than we need
96 * but we can work around that (see below). */
97 mc->magic = magic_open(MAGIC_MIME | MAGIC_ERROR);
99 mc->magic = magic_open(MAGIC_MIME_TYPE | MAGIC_ERROR);
103 /* This loads the default magic database.
104 * Point the MAGIC environment variable at your favourite .mgc
105 * file to load a non-default database. */
106 if (magic_load(mc->magic, NULL) == -1)
108 magic_close(mc->magic);
112 apr_pool_cleanup_register(result_pool, mc, close_magic_cookie,
113 apr_pool_cleanup_null);
123 svn_magic__detect_binary_mimetype(const char **mimetype,
124 const char *local_abspath,
125 svn_magic__cookie_t *magic_cookie,
126 apr_pool_t *result_pool,
127 apr_pool_t *scratch_pool)
129 const char *magic_mimetype = NULL;
130 #ifdef SVN_HAVE_LIBMAGIC
133 /* Do not ask libmagic for the mime-types of empty files.
134 * This prevents mime-types like "application/x-empty" from making
135 * Subversion treat empty files as binary. */
136 SVN_ERR(svn_io_stat(&finfo, local_abspath, APR_FINFO_SIZE, scratch_pool));
139 magic_mimetype = magic_file(magic_cookie->magic, local_abspath);
142 /* Only return binary mime-types. */
143 if (strncmp(magic_mimetype, "text/", 5) == 0)
144 magic_mimetype = NULL;
148 #ifndef MAGIC_MIME_TYPE
151 /* Strip off trailing stuff like " charset=ascii". */
152 p = strchr(magic_mimetype, ' ');
156 /* Make sure we got a valid mime type. */
157 err = svn_mime_type_validate(magic_mimetype, scratch_pool);
160 if (err->apr_err == SVN_ERR_BAD_MIME_TYPE)
162 svn_error_clear(err);
163 magic_mimetype = NULL;
166 return svn_error_trace(err);
170 /* The string is allocated from memory managed by libmagic
171 * so we must copy it to the result pool. */
172 magic_mimetype = apr_pstrdup(result_pool, magic_mimetype);
179 *mimetype = magic_mimetype;