summaryrefslogtreecommitdiff
path: root/gio/xdgmime/xdgmimecache.c
diff options
context:
space:
mode:
Diffstat (limited to 'gio/xdgmime/xdgmimecache.c')
-rw-r--r--gio/xdgmime/xdgmimecache.c139
1 files changed, 71 insertions, 68 deletions
diff --git a/gio/xdgmime/xdgmimecache.c b/gio/xdgmime/xdgmimecache.c
index 769b57836..3818180ae 100644
--- a/gio/xdgmime/xdgmimecache.c
+++ b/gio/xdgmime/xdgmimecache.c
@@ -19,10 +19,14 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
*/
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
@@ -39,7 +43,7 @@
#ifdef HAVE_MMAP
#include <sys/mman.h>
#else
-#warning Building xdgmime without MMAP support. Binary "mime.info" cache files will not be used.
+#warning Building xdgmime without MMAP support. Binary "mime.cache" files will not be used.
#endif
#include <sys/stat.h>
@@ -117,9 +121,9 @@ _xdg_mime_cache_new_from_file (const char *file_name)
int minor;
/* Open the file and map it into memory */
- do
+ do {
fd = open (file_name, O_RDONLY|_O_BINARY, 0);
- while (fd == -1 && errno == EINTR);
+ } while (fd == -1 && errno == EINTR);
if (fd < 0)
return NULL;
@@ -176,7 +180,7 @@ cache_magic_matchlet_compare_to_data (XdgMimeCache *cache,
xdg_uint32_t data_offset = GET_UINT32 (cache->buffer, offset + 16);
xdg_uint32_t mask_offset = GET_UINT32 (cache->buffer, offset + 20);
- int i, j;
+ xdg_uint32_t i, j;
for (i = range_start; i < range_start + range_length; i++)
{
@@ -199,16 +203,9 @@ cache_magic_matchlet_compare_to_data (XdgMimeCache *cache,
}
else
{
- for (j = 0; j < data_length; j++)
- {
- if (((unsigned char *)cache->buffer)[data_offset + j] != ((unsigned char *) data)[j + i])
- {
- valid_matchlet = FALSE;
- break;
- }
- }
+ valid_matchlet = memcmp(cache->buffer + data_offset, (unsigned char *)data + i, data_length) == 0;
}
-
+
if (valid_matchlet)
return TRUE;
}
@@ -225,7 +222,7 @@ cache_magic_matchlet_compare (XdgMimeCache *cache,
xdg_uint32_t n_children = GET_UINT32 (cache->buffer, offset + 24);
xdg_uint32_t child_offset = GET_UINT32 (cache->buffer, offset + 28);
- int i;
+ xdg_uint32_t i;
if (cache_magic_matchlet_compare_to_data (cache, offset, data, len))
{
@@ -255,7 +252,7 @@ cache_magic_compare_to_data (XdgMimeCache *cache,
xdg_uint32_t n_matchlets = GET_UINT32 (cache->buffer, offset + 8);
xdg_uint32_t matchlet_offset = GET_UINT32 (cache->buffer, offset + 12);
- int i;
+ xdg_uint32_t i;
for (i = 0; i < n_matchlets; i++)
{
@@ -275,15 +272,13 @@ static const char *
cache_magic_lookup_data (XdgMimeCache *cache,
const void *data,
size_t len,
- int *prio,
- const char *mime_types[],
- int n_mime_types)
+ int *prio)
{
xdg_uint32_t list_offset;
xdg_uint32_t n_entries;
xdg_uint32_t offset;
- int j, n;
+ xdg_uint32_t j;
*prio = 0;
@@ -299,21 +294,6 @@ cache_magic_lookup_data (XdgMimeCache *cache,
data, len, prio);
if (match)
return match;
- else
- {
- xdg_uint32_t mimetype_offset;
- const char *non_match;
-
- mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * j + 4);
- non_match = cache->buffer + mimetype_offset;
-
- for (n = 0; n < n_mime_types; n++)
- {
- if (mime_types[n] &&
- _xdg_mime_mime_type_equal (mime_types[n], non_match))
- mime_types[n] = NULL;
- }
- }
}
return NULL;
@@ -428,12 +408,14 @@ cache_glob_lookup_literal (const char *file_name,
static int
cache_glob_lookup_fnmatch (const char *file_name,
MimeWeight mime_types[],
- int n_mime_types)
+ int n_mime_types,
+ int case_sensitive_check)
{
const char *mime_type;
const char *ptr;
- int i, j, n;
+ int i, n;
+ xdg_uint32_t j;
n = 0;
for (i = 0; _caches[i]; i++)
@@ -454,16 +436,19 @@ cache_glob_lookup_fnmatch (const char *file_name,
xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j);
xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 4);
int weight = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 8);
+ int case_sensitive = weight & 0x100;
weight = weight & 0xff;
ptr = cache->buffer + offset;
mime_type = cache->buffer + mimetype_offset;
-
- /* FIXME: Not UTF-8 safe */
- if (fnmatch (ptr, file_name, 0) == 0)
+ if (case_sensitive_check || !case_sensitive)
{
- mime_types[n].mime = mime_type;
- mime_types[n].weight = weight;
- n++;
+ /* FIXME: Not UTF-8 safe */
+ if (fnmatch (ptr, file_name, 0) == 0)
+ {
+ mime_types[n].mime = mime_type;
+ mime_types[n].weight = weight;
+ n++;
+ }
}
}
@@ -492,7 +477,8 @@ cache_glob_node_lookup_suffix (XdgMimeCache *cache,
int weight;
int case_sensitive;
- int min, max, mid, n, i;
+ xdg_uint32_t i;
+ int min, max, mid, n;
character = file_name[len - 1];
@@ -578,17 +564,17 @@ cache_glob_lookup_suffix (const char *file_name,
n_entries = GET_UINT32 (cache->buffer, list_offset);
offset = GET_UINT32 (cache->buffer, list_offset + 4);
- n += cache_glob_node_lookup_suffix (cache,
- n_entries, offset,
- file_name, len,
- ignore_case,
- mime_types + n,
- n_mime_types - n);
- if (n == n_mime_types)
- break;
+ n = cache_glob_node_lookup_suffix (cache,
+ n_entries, offset,
+ file_name, len,
+ ignore_case,
+ mime_types,
+ n_mime_types);
+ if (n > 0)
+ return n;
}
- return n;
+ return 0;
}
static int compare_mime_weight (const void *a, const void *b)
@@ -680,14 +666,16 @@ cache_glob_lookup_file_name (const char *file_name,
if (n < 2)
n += cache_glob_lookup_suffix (file_name, len, TRUE, mimes + n, n_mimes - n);
- free (lower_case);
-
/* Last, try fnmatch */
+ if (n == 0)
+ n = cache_glob_lookup_fnmatch (lower_case, mimes, n_mimes, FALSE);
if (n < 2)
- n += cache_glob_lookup_fnmatch (file_name, mimes + n, n_mimes - n);
+ n += cache_glob_lookup_fnmatch (file_name, mimes + n, n_mimes - n, TRUE);
n = filter_out_dupes (mimes, n);
+ free (lower_case);
+
qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight);
if (n_mime_types < n)
@@ -743,8 +731,7 @@ cache_get_mime_type_for_data (const void *data,
if (cache->buffer == NULL)
continue;
- match = cache_magic_lookup_data (cache, data, len, &prio,
- mime_types, n_mime_types);
+ match = cache_magic_lookup_data (cache, data, len, &prio);
if (prio > priority)
{
priority = prio;
@@ -754,14 +741,27 @@ cache_get_mime_type_for_data (const void *data,
if (result_prio)
*result_prio = priority;
-
+
if (priority > 0)
- return mime_type;
+ {
+ /* Pick glob-result R where mime_type inherits from R */
+ for (n = 0; n < n_mime_types; n++)
+ {
+ if (mime_types[n] && _xdg_mime_cache_mime_type_subclass(mime_types[n], mime_type))
+ return mime_types[n];
+ }
+ if (n == 0)
+ {
+ /* No globs: return magic match */
+ return mime_type;
+ }
+ }
+ /* Pick first glob result, as fallback */
for (n = 0; n < n_mime_types; n++)
{
if (mime_types[n])
- return mime_types[n];
+ return mime_types[n];
}
return NULL;
@@ -844,7 +844,7 @@ _xdg_mime_cache_get_mime_type_for_file (const char *file_name,
mime_types, n);
if (!mime_type)
- mime_type = _xdg_binary_or_text_fallback(data, bytes_read);
+ mime_type = _xdg_binary_or_text_fallback (data, bytes_read);
free (data);
fclose (file);
@@ -905,7 +905,8 @@ _xdg_mime_cache_mime_type_subclass (const char *mime,
{
const char *umime, *ubase;
- int i, j, min, max, med, cmp;
+ xdg_uint32_t j;
+ int i, min, max, med, cmp;
umime = _xdg_mime_cache_unalias_mime_type (mime);
ubase = _xdg_mime_cache_unalias_mime_type (base);
@@ -995,7 +996,8 @@ _xdg_mime_cache_unalias_mime_type (const char *mime)
char **
_xdg_mime_cache_list_mime_parents (const char *mime)
{
- int i, j, k, l, p;
+ int i, l, p;
+ xdg_uint32_t j, k;
char *all_parents[128]; /* we'll stop at 128 */
char **result;
@@ -1120,6 +1122,7 @@ dump_glob_node (XdgMimeCache *cache,
xdg_uint32_t mime_offset;
xdg_uint32_t n_children;
xdg_uint32_t child_offset;
+ xdg_uint32_t k;
int i;
character = GET_UINT32 (cache->buffer, offset);
@@ -1134,15 +1137,15 @@ dump_glob_node (XdgMimeCache *cache,
printf ("\n");
if (child_offset)
{
- for (i = 0; i < n_children; i++)
- dump_glob_node (cache, child_offset + 20 * i, depth + 1);
+ for (k = 0; k < n_children; k++)
+ dump_glob_node (cache, child_offset + 20 * k, depth + 1);
}
}
void
_xdg_mime_cache_glob_dump (void)
{
- int i, j;
+ xdg_uint32_t i, j;
for (i = 0; _caches[i]; i++)
{
XdgMimeCache *cache = _caches[i];