📄 xdgmimemagic.c
字号:
/* -*- 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)#endifextern int errno;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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -