Index: base/third_party/xdg_mime/xdgmimemagic.c |
=================================================================== |
--- base/third_party/xdg_mime/xdgmimemagic.c (revision 0) |
+++ base/third_party/xdg_mime/xdgmimemagic.c (revision 0) |
@@ -0,0 +1,813 @@ |
+/* -*- mode: C; c-file-style: "gnu" -*- */ |
+/* xdgmimemagic.: Private file. Datastructure for storing magic files. |
+ * |
+ * More info can be found at http://www.freedesktop.org/standards/ |
+ * |
+ * Copyright (C) 2003 Red Hat, Inc. |
+ * Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu> |
+ * |
+ * Licensed under the Academic Free License version 2.0 |
+ * Or under the following terms: |
+ * |
+ * This library is free software; you can redistribute it and/or |
+ * modify it under the terms of the GNU Lesser General Public |
+ * License as published by the Free Software Foundation; either |
+ * version 2 of the License, or (at your option) any later version. |
+ * |
+ * This library is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+ * 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, write to the |
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
+ * Boston, MA 02111-1307, USA. |
+ */ |
+ |
+#ifdef HAVE_CONFIG_H |
+#include "config.h" |
+#endif |
+ |
+#include <assert.h> |
+#include "xdgmimemagic.h" |
+#include "xdgmimeint.h" |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <string.h> |
+#include <ctype.h> |
+#include <errno.h> |
+#include <limits.h> |
+ |
+#ifndef FALSE |
+#define FALSE (0) |
+#endif |
+ |
+#ifndef TRUE |
+#define TRUE (!FALSE) |
+#endif |
+ |
+#if !defined getc_unlocked && !defined HAVE_GETC_UNLOCKED |
+# define getc_unlocked(fp) getc (fp) |
+#endif |
+ |
+typedef struct XdgMimeMagicMatch XdgMimeMagicMatch; |
+typedef struct XdgMimeMagicMatchlet XdgMimeMagicMatchlet; |
+ |
+typedef enum |
+{ |
+ XDG_MIME_MAGIC_SECTION, |
+ XDG_MIME_MAGIC_MAGIC, |
+ XDG_MIME_MAGIC_ERROR, |
+ XDG_MIME_MAGIC_EOF |
+} XdgMimeMagicState; |
+ |
+struct XdgMimeMagicMatch |
+{ |
+ const char *mime_type; |
+ int priority; |
+ XdgMimeMagicMatchlet *matchlet; |
+ XdgMimeMagicMatch *next; |
+}; |
+ |
+ |
+struct XdgMimeMagicMatchlet |
+{ |
+ int indent; |
+ int offset; |
+ unsigned int value_length; |
+ unsigned char *value; |
+ unsigned char *mask; |
+ unsigned int range_length; |
+ unsigned int word_size; |
+ XdgMimeMagicMatchlet *next; |
+}; |
+ |
+ |
+struct XdgMimeMagic |
+{ |
+ XdgMimeMagicMatch *match_list; |
+ int max_extent; |
+}; |
+ |
+static XdgMimeMagicMatch * |
+_xdg_mime_magic_match_new (void) |
+{ |
+ return calloc (1, sizeof (XdgMimeMagicMatch)); |
+} |
+ |
+ |
+static XdgMimeMagicMatchlet * |
+_xdg_mime_magic_matchlet_new (void) |
+{ |
+ XdgMimeMagicMatchlet *matchlet; |
+ |
+ matchlet = malloc (sizeof (XdgMimeMagicMatchlet)); |
+ |
+ matchlet->indent = 0; |
+ matchlet->offset = 0; |
+ matchlet->value_length = 0; |
+ matchlet->value = NULL; |
+ matchlet->mask = NULL; |
+ matchlet->range_length = 1; |
+ matchlet->word_size = 1; |
+ matchlet->next = NULL; |
+ |
+ return matchlet; |
+} |
+ |
+ |
+static void |
+_xdg_mime_magic_matchlet_free (XdgMimeMagicMatchlet *mime_magic_matchlet) |
+{ |
+ if (mime_magic_matchlet) |
+ { |
+ if (mime_magic_matchlet->next) |
+ _xdg_mime_magic_matchlet_free (mime_magic_matchlet->next); |
+ if (mime_magic_matchlet->value) |
+ free (mime_magic_matchlet->value); |
+ if (mime_magic_matchlet->mask) |
+ free (mime_magic_matchlet->mask); |
+ free (mime_magic_matchlet); |
+ } |
+} |
+ |
+ |
+/* Frees mime_magic_match and the remainder of its list |
+ */ |
+static void |
+_xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match) |
+{ |
+ XdgMimeMagicMatch *ptr, *next; |
+ |
+ ptr = mime_magic_match; |
+ while (ptr) |
+ { |
+ next = ptr->next; |
+ |
+ if (ptr->mime_type) |
+ free ((void *) ptr->mime_type); |
+ if (ptr->matchlet) |
+ _xdg_mime_magic_matchlet_free (ptr->matchlet); |
+ free (ptr); |
+ |
+ ptr = next; |
+ } |
+} |
+ |
+/* Reads in a hunk of data until a newline character or a '\000' is hit. The |
+ * returned string is null terminated, and doesn't include the newline. |
+ */ |
+static unsigned char * |
+_xdg_mime_magic_read_to_newline (FILE *magic_file, |
+ int *end_of_file) |
+{ |
+ unsigned char *retval; |
+ int c; |
+ int len, pos; |
+ |
+ len = 128; |
+ pos = 0; |
+ retval = malloc (len); |
+ *end_of_file = FALSE; |
+ |
+ while (TRUE) |
+ { |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ { |
+ *end_of_file = TRUE; |
+ break; |
+ } |
+ if (c == '\n' || c == '\000') |
+ break; |
+ retval[pos++] = (unsigned char) c; |
+ if (pos % 128 == 127) |
+ { |
+ len = len + 128; |
+ retval = realloc (retval, len); |
+ } |
+ } |
+ |
+ retval[pos] = '\000'; |
+ return retval; |
+} |
+ |
+/* Returns the number read from the file, or -1 if no number could be read. |
+ */ |
+static int |
+_xdg_mime_magic_read_a_number (FILE *magic_file, |
+ int *end_of_file) |
+{ |
+ /* LONG_MAX is about 20 characters on my system */ |
+#define MAX_NUMBER_SIZE 30 |
+ char number_string[MAX_NUMBER_SIZE + 1]; |
+ int pos = 0; |
+ int c; |
+ long retval = -1; |
+ |
+ while (TRUE) |
+ { |
+ c = getc_unlocked (magic_file); |
+ |
+ if (c == EOF) |
+ { |
+ *end_of_file = TRUE; |
+ break; |
+ } |
+ if (! isdigit (c)) |
+ { |
+ ungetc (c, magic_file); |
+ break; |
+ } |
+ number_string[pos] = (char) c; |
+ pos++; |
+ if (pos == MAX_NUMBER_SIZE) |
+ break; |
+ } |
+ if (pos > 0) |
+ { |
+ number_string[pos] = '\000'; |
+ errno = 0; |
+ retval = strtol (number_string, NULL, 10); |
+ |
+ if ((retval < INT_MIN) || (retval > INT_MAX) || (errno != 0)) |
+ return -1; |
+ } |
+ |
+ return retval; |
+} |
+ |
+/* Headers are of the format: |
+ * [<priority>:<mime-type>] |
+ */ |
+static XdgMimeMagicState |
+_xdg_mime_magic_parse_header (FILE *magic_file, XdgMimeMagicMatch *match) |
+{ |
+ int c; |
+ char *buffer; |
+ char *end_ptr; |
+ int end_of_file = 0; |
+ |
+ assert (magic_file != NULL); |
+ assert (match != NULL); |
+ |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ return XDG_MIME_MAGIC_EOF; |
+ if (c != '[') |
+ return XDG_MIME_MAGIC_ERROR; |
+ |
+ match->priority = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); |
+ if (end_of_file) |
+ return XDG_MIME_MAGIC_EOF; |
+ if (match->priority == -1) |
+ return XDG_MIME_MAGIC_ERROR; |
+ |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ return XDG_MIME_MAGIC_EOF; |
+ if (c != ':') |
+ return XDG_MIME_MAGIC_ERROR; |
+ |
+ buffer = (char *)_xdg_mime_magic_read_to_newline (magic_file, &end_of_file); |
+ if (end_of_file) |
+ return XDG_MIME_MAGIC_EOF; |
+ |
+ end_ptr = buffer; |
+ while (*end_ptr != ']' && *end_ptr != '\000' && *end_ptr != '\n') |
+ end_ptr++; |
+ if (*end_ptr != ']') |
+ { |
+ free (buffer); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ *end_ptr = '\000'; |
+ |
+ match->mime_type = strdup (buffer); |
+ free (buffer); |
+ |
+ return XDG_MIME_MAGIC_MAGIC; |
+} |
+ |
+static XdgMimeMagicState |
+_xdg_mime_magic_parse_error (FILE *magic_file) |
+{ |
+ int c; |
+ |
+ while (1) |
+ { |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ return XDG_MIME_MAGIC_EOF; |
+ if (c == '\n') |
+ return XDG_MIME_MAGIC_SECTION; |
+ } |
+} |
+ |
+/* Headers are of the format: |
+ * [ indent ] ">" start-offset "=" value |
+ * [ "&" mask ] [ "~" word-size ] [ "+" range-length ] "\n" |
+ */ |
+static XdgMimeMagicState |
+_xdg_mime_magic_parse_magic_line (FILE *magic_file, |
+ XdgMimeMagicMatch *match) |
+{ |
+ XdgMimeMagicMatchlet *matchlet; |
+ int c; |
+ int end_of_file; |
+ int indent = 0; |
+ int bytes_read; |
+ |
+ assert (magic_file != NULL); |
+ |
+ /* Sniff the buffer to make sure it's a valid line */ |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ return XDG_MIME_MAGIC_EOF; |
+ else if (c == '[') |
+ { |
+ ungetc (c, magic_file); |
+ return XDG_MIME_MAGIC_SECTION; |
+ } |
+ else if (c == '\n') |
+ return XDG_MIME_MAGIC_MAGIC; |
+ |
+ /* At this point, it must be a digit or a '>' */ |
+ end_of_file = FALSE; |
+ if (isdigit (c)) |
+ { |
+ ungetc (c, magic_file); |
+ indent = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); |
+ if (end_of_file) |
+ return XDG_MIME_MAGIC_EOF; |
+ if (indent == -1) |
+ return XDG_MIME_MAGIC_ERROR; |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ return XDG_MIME_MAGIC_EOF; |
+ } |
+ |
+ if (c != '>') |
+ return XDG_MIME_MAGIC_ERROR; |
+ |
+ matchlet = _xdg_mime_magic_matchlet_new (); |
+ matchlet->indent = indent; |
+ matchlet->offset = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); |
+ if (end_of_file) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_EOF; |
+ } |
+ if (matchlet->offset == -1) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_EOF; |
+ } |
+ else if (c != '=') |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ |
+ /* Next two bytes determine how long the value is */ |
+ matchlet->value_length = 0; |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_EOF; |
+ } |
+ matchlet->value_length = c & 0xFF; |
+ matchlet->value_length = matchlet->value_length << 8; |
+ |
+ c = getc_unlocked (magic_file); |
+ if (c == EOF) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_EOF; |
+ } |
+ matchlet->value_length = matchlet->value_length + (c & 0xFF); |
+ |
+ matchlet->value = malloc (matchlet->value_length); |
+ |
+ /* OOM */ |
+ if (matchlet->value == NULL) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ bytes_read = fread (matchlet->value, 1, matchlet->value_length, magic_file); |
+ if (bytes_read != matchlet->value_length) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ if (feof (magic_file)) |
+ return XDG_MIME_MAGIC_EOF; |
+ else |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ |
+ c = getc_unlocked (magic_file); |
+ if (c == '&') |
+ { |
+ matchlet->mask = malloc (matchlet->value_length); |
+ /* OOM */ |
+ if (matchlet->mask == NULL) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ bytes_read = fread (matchlet->mask, 1, matchlet->value_length, magic_file); |
+ if (bytes_read != matchlet->value_length) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ if (feof (magic_file)) |
+ return XDG_MIME_MAGIC_EOF; |
+ else |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ c = getc_unlocked (magic_file); |
+ } |
+ |
+ if (c == '~') |
+ { |
+ matchlet->word_size = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); |
+ if (end_of_file) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_EOF; |
+ } |
+ if (matchlet->word_size != 0 && |
+ matchlet->word_size != 1 && |
+ matchlet->word_size != 2 && |
+ matchlet->word_size != 4) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ c = getc_unlocked (magic_file); |
+ } |
+ |
+ if (c == '+') |
+ { |
+ matchlet->range_length = _xdg_mime_magic_read_a_number (magic_file, &end_of_file); |
+ if (end_of_file) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_EOF; |
+ } |
+ if (matchlet->range_length == -1) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ c = getc_unlocked (magic_file); |
+ } |
+ |
+ |
+ if (c == '\n') |
+ { |
+ /* We clean up the matchlet, byte swapping if needed */ |
+ if (matchlet->word_size > 1) |
+ { |
+ int i; |
+ if (matchlet->value_length % matchlet->word_size != 0) |
+ { |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ return XDG_MIME_MAGIC_ERROR; |
+ } |
+ /* FIXME: need to get this defined in a <config.h> style file */ |
+#if LITTLE_ENDIAN |
+ for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size) |
+ { |
+ if (matchlet->word_size == 2) |
+ *((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i))); |
+ else if (matchlet->word_size == 4) |
+ *((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i))); |
+ if (matchlet->mask) |
+ { |
+ if (matchlet->word_size == 2) |
+ *((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i))); |
+ else if (matchlet->word_size == 4) |
+ *((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i))); |
+ |
+ } |
+ } |
+#endif |
+ } |
+ |
+ matchlet->next = match->matchlet; |
+ match->matchlet = matchlet; |
+ |
+ |
+ return XDG_MIME_MAGIC_MAGIC; |
+ } |
+ |
+ _xdg_mime_magic_matchlet_free (matchlet); |
+ if (c == EOF) |
+ return XDG_MIME_MAGIC_EOF; |
+ |
+ return XDG_MIME_MAGIC_ERROR; |
+} |
+ |
+static int |
+_xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet, |
+ const void *data, |
+ size_t len) |
+{ |
+ int i, j; |
+ for (i = matchlet->offset; i < matchlet->offset + matchlet->range_length; i++) |
+ { |
+ int valid_matchlet = TRUE; |
+ |
+ if (i + matchlet->value_length > len) |
+ return FALSE; |
+ |
+ if (matchlet->mask) |
+ { |
+ for (j = 0; j < matchlet->value_length; j++) |
+ { |
+ if ((matchlet->value[j] & matchlet->mask[j]) != |
+ ((((unsigned char *) data)[j + i]) & matchlet->mask[j])) |
+ { |
+ valid_matchlet = FALSE; |
+ break; |
+ } |
+ } |
+ } |
+ else |
+ { |
+ for (j = 0; j < matchlet->value_length; j++) |
+ { |
+ if (matchlet->value[j] != ((unsigned char *) data)[j + i]) |
+ { |
+ valid_matchlet = FALSE; |
+ break; |
+ } |
+ } |
+ } |
+ if (valid_matchlet) |
+ return TRUE; |
+ } |
+ return FALSE; |
+} |
+ |
+static int |
+_xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet, |
+ const void *data, |
+ size_t len, |
+ int indent) |
+{ |
+ while ((matchlet != NULL) && (matchlet->indent == indent)) |
+ { |
+ if (_xdg_mime_magic_matchlet_compare_to_data (matchlet, data, len)) |
+ { |
+ if ((matchlet->next == NULL) || |
+ (matchlet->next->indent <= indent)) |
+ return TRUE; |
+ |
+ if (_xdg_mime_magic_matchlet_compare_level (matchlet->next, |
+ data, |
+ len, |
+ indent + 1)) |
+ return TRUE; |
+ } |
+ |
+ do |
+ { |
+ matchlet = matchlet->next; |
+ } |
+ while (matchlet && matchlet->indent > indent); |
+ } |
+ |
+ return FALSE; |
+} |
+ |
+static int |
+_xdg_mime_magic_match_compare_to_data (XdgMimeMagicMatch *match, |
+ const void *data, |
+ size_t len) |
+{ |
+ return _xdg_mime_magic_matchlet_compare_level (match->matchlet, data, len, 0); |
+} |
+ |
+static void |
+_xdg_mime_magic_insert_match (XdgMimeMagic *mime_magic, |
+ XdgMimeMagicMatch *match) |
+{ |
+ XdgMimeMagicMatch *list; |
+ |
+ if (mime_magic->match_list == NULL) |
+ { |
+ mime_magic->match_list = match; |
+ return; |
+ } |
+ |
+ if (match->priority > mime_magic->match_list->priority) |
+ { |
+ match->next = mime_magic->match_list; |
+ mime_magic->match_list = match; |
+ return; |
+ } |
+ |
+ list = mime_magic->match_list; |
+ while (list->next != NULL) |
+ { |
+ if (list->next->priority < match->priority) |
+ { |
+ match->next = list->next; |
+ list->next = match; |
+ return; |
+ } |
+ list = list->next; |
+ } |
+ list->next = match; |
+ match->next = NULL; |
+} |
+ |
+XdgMimeMagic * |
+_xdg_mime_magic_new (void) |
+{ |
+ return calloc (1, sizeof (XdgMimeMagic)); |
+} |
+ |
+void |
+_xdg_mime_magic_free (XdgMimeMagic *mime_magic) |
+{ |
+ if (mime_magic) { |
+ _xdg_mime_magic_match_free (mime_magic->match_list); |
+ free (mime_magic); |
+ } |
+} |
+ |
+int |
+_xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic) |
+{ |
+ return mime_magic->max_extent; |
+} |
+ |
+const char * |
+_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic, |
+ const void *data, |
+ size_t len, |
+ int *result_prio, |
+ const char *mime_types[], |
+ int n_mime_types) |
+{ |
+ XdgMimeMagicMatch *match; |
+ const char *mime_type; |
+ int n; |
+ int prio; |
+ |
+ prio = 0; |
+ mime_type = NULL; |
+ for (match = mime_magic->match_list; match; match = match->next) |
+ { |
+ if (_xdg_mime_magic_match_compare_to_data (match, data, len)) |
+ { |
+ prio = match->priority; |
+ mime_type = match->mime_type; |
+ break; |
+ } |
+ else |
+ { |
+ for (n = 0; n < n_mime_types; n++) |
+ { |
+ if (mime_types[n] && |
+ _xdg_mime_mime_type_equal (mime_types[n], match->mime_type)) |
+ mime_types[n] = NULL; |
+ } |
+ } |
+ } |
+ |
+ if (mime_type == NULL) |
+ { |
+ for (n = 0; n < n_mime_types; n++) |
+ { |
+ if (mime_types[n]) |
+ mime_type = mime_types[n]; |
+ } |
+ } |
+ |
+ if (result_prio) |
+ *result_prio = prio; |
+ |
+ return mime_type; |
+} |
+ |
+static void |
+_xdg_mime_update_mime_magic_extents (XdgMimeMagic *mime_magic) |
+{ |
+ XdgMimeMagicMatch *match; |
+ int max_extent = 0; |
+ |
+ for (match = mime_magic->match_list; match; match = match->next) |
+ { |
+ XdgMimeMagicMatchlet *matchlet; |
+ |
+ for (matchlet = match->matchlet; matchlet; matchlet = matchlet->next) |
+ { |
+ int extent; |
+ |
+ extent = matchlet->value_length + matchlet->offset + matchlet->range_length; |
+ if (max_extent < extent) |
+ max_extent = extent; |
+ } |
+ } |
+ |
+ mime_magic->max_extent = max_extent; |
+} |
+ |
+static XdgMimeMagicMatchlet * |
+_xdg_mime_magic_matchlet_mirror (XdgMimeMagicMatchlet *matchlets) |
+{ |
+ XdgMimeMagicMatchlet *new_list; |
+ XdgMimeMagicMatchlet *tmp; |
+ |
+ if ((matchlets == NULL) || (matchlets->next == NULL)) |
+ return matchlets; |
+ |
+ new_list = NULL; |
+ tmp = matchlets; |
+ while (tmp != NULL) |
+ { |
+ XdgMimeMagicMatchlet *matchlet; |
+ |
+ matchlet = tmp; |
+ tmp = tmp->next; |
+ matchlet->next = new_list; |
+ new_list = matchlet; |
+ } |
+ |
+ return new_list; |
+ |
+} |
+ |
+static void |
+_xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic, |
+ FILE *magic_file) |
+{ |
+ XdgMimeMagicState state; |
+ XdgMimeMagicMatch *match = NULL; /* Quiet compiler */ |
+ |
+ state = XDG_MIME_MAGIC_SECTION; |
+ |
+ while (state != XDG_MIME_MAGIC_EOF) |
+ { |
+ switch (state) |
+ { |
+ case XDG_MIME_MAGIC_SECTION: |
+ match = _xdg_mime_magic_match_new (); |
+ state = _xdg_mime_magic_parse_header (magic_file, match); |
+ if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR) |
+ _xdg_mime_magic_match_free (match); |
+ break; |
+ case XDG_MIME_MAGIC_MAGIC: |
+ state = _xdg_mime_magic_parse_magic_line (magic_file, match); |
+ if (state == XDG_MIME_MAGIC_SECTION || |
+ (state == XDG_MIME_MAGIC_EOF && match->mime_type)) |
+ { |
+ match->matchlet = _xdg_mime_magic_matchlet_mirror (match->matchlet); |
+ _xdg_mime_magic_insert_match (mime_magic, match); |
+ } |
+ else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR) |
+ _xdg_mime_magic_match_free (match); |
+ break; |
+ case XDG_MIME_MAGIC_ERROR: |
+ state = _xdg_mime_magic_parse_error (magic_file); |
+ break; |
+ case XDG_MIME_MAGIC_EOF: |
+ default: |
+ /* Make the compiler happy */ |
+ assert (0); |
+ } |
+ } |
+ _xdg_mime_update_mime_magic_extents (mime_magic); |
+} |
+ |
+void |
+_xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic, |
+ const char *file_name) |
+{ |
+ FILE *magic_file; |
+ char header[12]; |
+ |
+ magic_file = fopen (file_name, "r"); |
+ |
+ if (magic_file == NULL) |
+ return; |
+ |
+ if (fread (header, 1, 12, magic_file) == 12) |
+ { |
+ if (memcmp ("MIME-Magic\0\n", header, 12) == 0) |
+ _xdg_mime_magic_read_magic_file (mime_magic, magic_file); |
+ } |
+ |
+ fclose (magic_file); |
+} |