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"
37 #include "svn_private_config.h"
39 #include "private/svn_magic.h"
41 #ifdef SVN_HAVE_LIBMAGIC
45 struct svn_magic__cookie_t {
46 #ifdef SVN_HAVE_LIBMAGIC
53 #ifdef SVN_HAVE_LIBMAGIC
54 /* Close the magic database. */
56 close_magic_cookie(void *baton)
58 svn_magic__cookie_t *mc = (svn_magic__cookie_t*)baton;
59 magic_close(mc->magic);
65 svn_magic__init(svn_magic__cookie_t **magic_cookie,
66 apr_pool_t *result_pool)
69 svn_magic__cookie_t *mc = NULL;
71 #ifdef SVN_HAVE_LIBMAGIC
72 mc = apr_palloc(result_pool, sizeof(*mc));
74 /* Initialise libmagic. */
75 #ifndef MAGIC_MIME_TYPE
76 /* Some old versions of libmagic don't support MAGIC_MIME_TYPE.
77 * We can use MAGIC_MIME instead. It returns more than we need
78 * but we can work around that (see below). */
79 mc->magic = magic_open(MAGIC_MIME | MAGIC_ERROR);
81 mc->magic = magic_open(MAGIC_MIME_TYPE | MAGIC_ERROR);
85 /* This loads the default magic database.
86 * Point the MAGIC environment variable at your favourite .mgc
87 * file to load a non-default database. */
88 if (magic_load(mc->magic, NULL) == -1)
90 magic_close(mc->magic);
94 apr_pool_cleanup_register(result_pool, mc, close_magic_cookie,
95 apr_pool_cleanup_null);
103 svn_magic__detect_binary_mimetype(const char **mimetype,
104 const char *local_abspath,
105 svn_magic__cookie_t *magic_cookie,
106 apr_pool_t *result_pool,
107 apr_pool_t *scratch_pool)
109 const char *magic_mimetype = NULL;
110 #ifdef SVN_HAVE_LIBMAGIC
113 /* Do not ask libmagic for the mime-types of empty files.
114 * This prevents mime-types like "application/x-empty" from making
115 * Subversion treat empty files as binary. */
116 SVN_ERR(svn_io_stat(&finfo, local_abspath, APR_FINFO_SIZE, scratch_pool));
119 magic_mimetype = magic_file(magic_cookie->magic, local_abspath);
122 /* Only return binary mime-types. */
123 if (strncmp(magic_mimetype, "text/", 5) == 0)
124 magic_mimetype = NULL;
128 #ifndef MAGIC_MIME_TYPE
131 /* Strip off trailing stuff like " charset=ascii". */
132 p = strchr(magic_mimetype, ' ');
136 /* Make sure we got a valid mime type. */
137 err = svn_mime_type_validate(magic_mimetype, scratch_pool);
140 if (err->apr_err == SVN_ERR_BAD_MIME_TYPE)
142 svn_error_clear(err);
143 magic_mimetype = NULL;
146 return svn_error_trace(err);
150 /* The string is allocated from memory managed by libmagic
151 * so we must copy it to the result pool. */
152 magic_mimetype = apr_pstrdup(result_pool, magic_mimetype);
159 *mimetype = magic_mimetype;