LCOV - code coverage report
Current view: top level - lib/xdgmime - xdgmimemagic.c (source / functions) Hit Total Coverage
Test: libcitadel.info Lines: 265 361 73.4 %
Date: 2010-12-07 Functions: 19 21 90.5 %
Branches: 148 254 58.3 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C; c-file-style: "gnu" -*- */
       2                 :            : /* xdgmimemagic.: Private file.  Datastructure for storing magic files.
       3                 :            :  *
       4                 :            :  * More info can be found at http://www.freedesktop.org/standards/
       5                 :            :  *
       6                 :            :  * Copyright (C) 2003  Red Hat, Inc.
       7                 :            :  * Copyright (C) 2003  Jonathan Blandford <jrb@alum.mit.edu>
       8                 :            :  *
       9                 :            :  * Licensed under the Academic Free License version 2.0
      10                 :            :  * Or under the following terms:
      11                 :            :  *
      12                 :            :  * This library is free software; you can redistribute it and/or
      13                 :            :  * modify it under the terms of the GNU Lesser General Public
      14                 :            :  * License as published by the Free Software Foundation; either
      15                 :            :  * version 2 of the License, or (at your option) any later version.
      16                 :            :  *
      17                 :            :  * This library is distributed in the hope that it will be useful,
      18                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      20                 :            :  * Lesser General Public License for more details.
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public
      23                 :            :  * License along with this library; if not, write to the
      24                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      25                 :            :  * Boston, MA 02111-1307, USA.
      26                 :            :  */
      27                 :            : 
      28                 :            : #ifdef HAVE_CONFIG_H
      29                 :            : #include <config.h>
      30                 :            : #endif
      31                 :            : 
      32                 :            : #include <assert.h>
      33                 :            : #include "xdgmimemagic.h"
      34                 :            : #include "xdgmimeint.h"
      35                 :            : #include <stdio.h>
      36                 :            : #include <stdlib.h>
      37                 :            : #include <string.h>
      38                 :            : #include <ctype.h>
      39                 :            : #include <errno.h>
      40                 :            : #include <limits.h>
      41                 :            : 
      42                 :            : #ifndef FALSE
      43                 :            : #define FALSE   (0)
      44                 :            : #endif
      45                 :            : 
      46                 :            : #ifndef TRUE
      47                 :            : #define TRUE    (!FALSE)
      48                 :            : #endif
      49                 :            : 
      50                 :            : #if !defined getc_unlocked && !defined HAVE_GETC_UNLOCKED
      51                 :            : #define getc_unlocked(fp) getc (fp)
      52                 :            : #endif
      53                 :            : 
      54                 :            : typedef struct XdgMimeMagicMatch XdgMimeMagicMatch;
      55                 :            : typedef struct XdgMimeMagicMatchlet XdgMimeMagicMatchlet;
      56                 :            : 
      57                 :            : typedef enum
      58                 :            : {
      59                 :            :   XDG_MIME_MAGIC_SECTION,
      60                 :            :   XDG_MIME_MAGIC_MAGIC,
      61                 :            :   XDG_MIME_MAGIC_ERROR,
      62                 :            :   XDG_MIME_MAGIC_EOF
      63                 :            : } XdgMimeMagicState;
      64                 :            : 
      65                 :            : struct XdgMimeMagicMatch
      66                 :            : {
      67                 :            :   const char *mime_type;
      68                 :            :   int priority;
      69                 :            :   XdgMimeMagicMatchlet *matchlet;
      70                 :            :   XdgMimeMagicMatch *next;
      71                 :            : };
      72                 :            : 
      73                 :            : 
      74                 :            : struct XdgMimeMagicMatchlet
      75                 :            : {
      76                 :            :   int indent;
      77                 :            :   int offset;
      78                 :            :   unsigned int value_length;
      79                 :            :   unsigned char *value;
      80                 :            :   unsigned char *mask;
      81                 :            :   unsigned int range_length;
      82                 :            :   unsigned int word_size;
      83                 :            :   XdgMimeMagicMatchlet *next;
      84                 :            : };
      85                 :            : 
      86                 :            : 
      87                 :            : struct XdgMimeMagic
      88                 :            : {
      89                 :            :   XdgMimeMagicMatch *match_list;
      90                 :            :   int max_extent;
      91                 :            : };
      92                 :            : 
      93                 :            : static XdgMimeMagicMatch *
      94                 :       1950 : _xdg_mime_magic_match_new (void)
      95                 :            : {
      96                 :       1950 :   return calloc (1, sizeof (XdgMimeMagicMatch));
      97                 :            : }
      98                 :            : 
      99                 :            : 
     100                 :            : static XdgMimeMagicMatchlet *
     101                 :       4578 : _xdg_mime_magic_matchlet_new (void)
     102                 :            : {
     103                 :            :   XdgMimeMagicMatchlet *matchlet;
     104                 :            : 
     105                 :       4578 :   matchlet = malloc (sizeof (XdgMimeMagicMatchlet));
     106                 :            : 
     107                 :       4578 :   matchlet->indent = 0;
     108                 :       4578 :   matchlet->offset = 0;
     109                 :       4578 :   matchlet->value_length = 0;
     110                 :       4578 :   matchlet->value = NULL;
     111                 :       4578 :   matchlet->mask = NULL;
     112                 :       4578 :   matchlet->range_length = 1;
     113                 :       4578 :   matchlet->word_size = 1;
     114                 :       4578 :   matchlet->next = NULL;
     115                 :            : 
     116                 :       4578 :   return matchlet;
     117                 :            : }
     118                 :            : 
     119                 :            : 
     120                 :            : static void
     121                 :       4578 : _xdg_mime_magic_matchlet_free (XdgMimeMagicMatchlet *mime_magic_matchlet)
     122                 :            : {
     123         [ +  - ]:       4578 :   if (mime_magic_matchlet)
     124                 :            :     {
     125         [ +  + ]:       4578 :       if (mime_magic_matchlet->next)
     126                 :       2628 :         _xdg_mime_magic_matchlet_free (mime_magic_matchlet->next);
     127         [ +  - ]:       4578 :       if (mime_magic_matchlet->value)
     128                 :       4578 :         free (mime_magic_matchlet->value);
     129         [ +  + ]:       4578 :       if (mime_magic_matchlet->mask)
     130                 :         90 :         free (mime_magic_matchlet->mask);
     131                 :       4578 :       free (mime_magic_matchlet);
     132                 :            :     }
     133                 :       4578 : }
     134                 :            : 
     135                 :            : 
     136                 :            : /* Frees mime_magic_match and the remainder of its list
     137                 :            :  */
     138                 :            : static void
     139                 :          6 : _xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match)
     140                 :            : {
     141                 :            :   XdgMimeMagicMatch *ptr, *next;
     142                 :            : 
     143                 :          6 :   ptr = mime_magic_match;
     144         [ +  + ]:       1956 :   while (ptr)
     145                 :            :     {
     146                 :       1950 :       next = ptr->next;
     147                 :            : 
     148         [ +  - ]:       1950 :       if (ptr->mime_type)
     149                 :       1950 :         free ((void *) ptr->mime_type);
     150         [ +  - ]:       1950 :       if (ptr->matchlet)
     151                 :       1950 :         _xdg_mime_magic_matchlet_free (ptr->matchlet);
     152                 :       1950 :       free (ptr);
     153                 :            : 
     154                 :       1950 :       ptr = next;
     155                 :            :     }
     156                 :          6 : }
     157                 :            : 
     158                 :            : /* Reads in a hunk of data until a newline character or a '\000' is hit.  The
     159                 :            :  * returned string is null terminated, and doesn't include the newline.
     160                 :            :  */
     161                 :            : static unsigned char *
     162                 :       1950 : _xdg_mime_magic_read_to_newline (FILE *magic_file,
     163                 :            :                                  int  *end_of_file)
     164                 :            : {
     165                 :            :   unsigned char *retval;
     166                 :            :   int c;
     167                 :            :   int len, pos;
     168                 :            : 
     169                 :       1950 :   len = 128;
     170                 :       1950 :   pos = 0;
     171                 :       1950 :   retval = malloc (len);
     172                 :       1950 :   *end_of_file = FALSE;
     173                 :            : 
     174                 :            :   while (TRUE)
     175                 :            :     {
     176                 :      42672 :       c = getc_unlocked (magic_file);
     177         [ -  + ]:      42672 :       if (c == EOF)
     178                 :            :         {
     179                 :          0 :           *end_of_file = TRUE;
     180                 :          0 :           break;
     181                 :            :         }
     182 [ +  + ][ +  - ]:      42672 :       if (c == '\n' || c == '\000')
     183                 :            :         break;
     184                 :      40722 :       retval[pos++] = (unsigned char) c;
     185         [ -  + ]:      40722 :       if (pos % 128 == 127)
     186                 :            :         {
     187                 :          0 :           len = len + 128;
     188                 :          0 :           retval = realloc (retval, len);
     189                 :            :         }
     190                 :      40722 :     }
     191                 :            : 
     192                 :       1950 :   retval[pos] = '\000';
     193                 :       1950 :   return retval;
     194                 :            : }
     195                 :            : 
     196                 :            : /* Returns the number read from the file, or -1 if no number could be read.
     197                 :            :  */
     198                 :            : static int
     199                 :       8250 : _xdg_mime_magic_read_a_number (FILE *magic_file,
     200                 :            :                                int  *end_of_file)
     201                 :            : {
     202                 :            :   /* LONG_MAX is about 20 characters on my system */
     203                 :            : #define MAX_NUMBER_SIZE 30
     204                 :            :   char number_string[MAX_NUMBER_SIZE + 1];
     205                 :       8250 :   int pos = 0;
     206                 :            :   int c;
     207                 :       8250 :   long retval = -1;
     208                 :            : 
     209                 :            :   while (TRUE)
     210                 :            :     {
     211                 :      20442 :       c = getc_unlocked (magic_file);
     212                 :            : 
     213         [ -  + ]:      20442 :       if (c == EOF)
     214                 :            :         {
     215                 :          0 :           *end_of_file = TRUE;
     216                 :          0 :           break;
     217                 :            :         }
     218         [ +  + ]:      20442 :       if (! isdigit (c))
     219                 :            :         {
     220                 :       8250 :           ungetc (c, magic_file);
     221                 :       8250 :           break;
     222                 :            :         }
     223                 :      12192 :       number_string[pos] = (char) c;
     224                 :      12192 :       pos++;
     225         [ -  + ]:      12192 :       if (pos == MAX_NUMBER_SIZE)
     226                 :          0 :         break;
     227                 :      12192 :     }
     228         [ +  - ]:       8250 :   if (pos > 0)
     229                 :            :     {
     230                 :       8250 :       number_string[pos] = '\000';
     231                 :       8250 :       errno = 0;
     232                 :       8250 :       retval = strtol (number_string, NULL, 10);
     233                 :            : 
     234         [ -  + ]:       8250 :       if ((retval < INT_MIN) || (retval > INT_MAX) || (errno != 0))
     235                 :          0 :         return -1;
     236                 :            :     }
     237                 :            : 
     238                 :       8250 :   return retval;
     239                 :            : }
     240                 :            : 
     241                 :            : /* Headers are of the format:
     242                 :            :  * [<priority>:<mime-type>]
     243                 :            :  */
     244                 :            : static XdgMimeMagicState
     245                 :       1950 : _xdg_mime_magic_parse_header (FILE *magic_file, XdgMimeMagicMatch *match)
     246                 :            : {
     247                 :            :   int c;
     248                 :            :   char *buffer;
     249                 :            :   char *end_ptr;
     250                 :       1950 :   int end_of_file = 0;
     251                 :            : 
     252         [ -  + ]:       1950 :   assert (magic_file != NULL);
     253         [ -  + ]:       1950 :   assert (match != NULL);
     254                 :            : 
     255                 :       1950 :   c = getc_unlocked (magic_file);
     256         [ -  + ]:       1950 :   if (c == EOF)
     257                 :          0 :     return XDG_MIME_MAGIC_EOF;
     258         [ -  + ]:       1950 :   if (c != '[')
     259                 :          0 :     return XDG_MIME_MAGIC_ERROR;
     260                 :            : 
     261                 :       1950 :   match->priority = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
     262         [ -  + ]:       1950 :   if (end_of_file)
     263                 :          0 :     return XDG_MIME_MAGIC_EOF;
     264         [ -  + ]:       1950 :   if (match->priority == -1)
     265                 :          0 :     return XDG_MIME_MAGIC_ERROR;
     266                 :            : 
     267                 :       1950 :   c = getc_unlocked (magic_file);
     268         [ -  + ]:       1950 :   if (c == EOF)
     269                 :          0 :     return XDG_MIME_MAGIC_EOF;
     270         [ -  + ]:       1950 :   if (c != ':')
     271                 :          0 :     return XDG_MIME_MAGIC_ERROR;
     272                 :            : 
     273                 :       1950 :   buffer = (char *)_xdg_mime_magic_read_to_newline (magic_file, &end_of_file);
     274         [ -  + ]:       1950 :   if (end_of_file)
     275                 :          0 :     return XDG_MIME_MAGIC_EOF;
     276                 :            : 
     277                 :       1950 :   end_ptr = buffer;
     278 [ +  + ][ +  - ]:      40722 :   while (*end_ptr != ']' && *end_ptr != '\000' && *end_ptr != '\n')
                 [ +  - ]
     279                 :      38772 :     end_ptr++;
     280         [ -  + ]:       1950 :   if (*end_ptr != ']')
     281                 :            :     {
     282                 :          0 :       free (buffer);
     283                 :          0 :       return XDG_MIME_MAGIC_ERROR;
     284                 :            :     }
     285                 :       1950 :   *end_ptr = '\000';
     286                 :            : 
     287                 :       1950 :   match->mime_type = strdup (buffer);
     288                 :       1950 :   free (buffer);
     289                 :            : 
     290                 :       1950 :   return XDG_MIME_MAGIC_MAGIC;
     291                 :            : }
     292                 :            : 
     293                 :            : static XdgMimeMagicState
     294                 :          0 : _xdg_mime_magic_parse_error (FILE *magic_file)
     295                 :            : {
     296                 :            :   int c;
     297                 :            : 
     298                 :            :   while (1)
     299                 :            :     {
     300                 :          0 :       c = getc_unlocked (magic_file);
     301         [ #  # ]:          0 :       if (c == EOF)
     302                 :          0 :         return XDG_MIME_MAGIC_EOF;
     303         [ #  # ]:          0 :       if (c == '\n')
     304                 :          0 :         return XDG_MIME_MAGIC_SECTION;
     305                 :          0 :     }
     306                 :            : }
     307                 :            : 
     308                 :            : /* Headers are of the format:
     309                 :            :  * [ indent ] ">" start-offset "=" value
     310                 :            :  * [ "&" mask ] [ "~" word-size ] [ "+" range-length ] "\n"
     311                 :            :  */
     312                 :            : static XdgMimeMagicState
     313                 :       6528 : _xdg_mime_magic_parse_magic_line (FILE              *magic_file,
     314                 :            :                                   XdgMimeMagicMatch *match)
     315                 :            : {
     316                 :            :   XdgMimeMagicMatchlet *matchlet;
     317                 :            :   int c;
     318                 :            :   int end_of_file;
     319                 :       6528 :   int indent = 0;
     320                 :            :   int bytes_read;
     321                 :            : 
     322         [ -  + ]:       6528 :   assert (magic_file != NULL);
     323                 :            : 
     324                 :            :   /* Sniff the buffer to make sure it's a valid line */
     325                 :       6528 :   c = getc_unlocked (magic_file);
     326         [ +  + ]:       6528 :   if (c == EOF)
     327                 :          6 :     return XDG_MIME_MAGIC_EOF;
     328         [ +  + ]:       6522 :   else if (c == '[')
     329                 :            :     {
     330                 :       1944 :       ungetc (c, magic_file);
     331                 :       1944 :       return XDG_MIME_MAGIC_SECTION;
     332                 :            :     }
     333         [ -  + ]:       4578 :   else if (c == '\n')
     334                 :          0 :     return XDG_MIME_MAGIC_MAGIC;
     335                 :            : 
     336                 :            :   /* At this point, it must be a digit or a '>' */
     337                 :       4578 :   end_of_file = FALSE;
     338         [ +  + ]:       4578 :   if (isdigit (c))
     339                 :            :     {
     340                 :       1140 :       ungetc (c, magic_file);
     341                 :       1140 :       indent = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
     342         [ -  + ]:       1140 :       if (end_of_file)
     343                 :          0 :         return XDG_MIME_MAGIC_EOF;
     344         [ -  + ]:       1140 :       if (indent == -1)
     345                 :          0 :         return XDG_MIME_MAGIC_ERROR;
     346                 :       1140 :       c = getc_unlocked (magic_file);
     347         [ -  + ]:       1140 :       if (c == EOF)
     348                 :          0 :         return XDG_MIME_MAGIC_EOF;
     349                 :            :     }
     350                 :            : 
     351         [ -  + ]:       4578 :   if (c != '>')
     352                 :          0 :     return XDG_MIME_MAGIC_ERROR;
     353                 :            : 
     354                 :       4578 :   matchlet = _xdg_mime_magic_matchlet_new ();
     355                 :       4578 :   matchlet->indent = indent;
     356                 :       4578 :   matchlet->offset = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
     357         [ -  + ]:       4578 :   if (end_of_file)
     358                 :            :     {
     359                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     360                 :          0 :       return XDG_MIME_MAGIC_EOF;
     361                 :            :     }
     362         [ -  + ]:       4578 :   if (matchlet->offset == -1)
     363                 :            :     {
     364                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     365                 :          0 :       return XDG_MIME_MAGIC_ERROR;
     366                 :            :     }
     367                 :       4578 :   c = getc_unlocked (magic_file);
     368         [ -  + ]:       4578 :   if (c == EOF)
     369                 :            :     {
     370                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     371                 :          0 :       return XDG_MIME_MAGIC_EOF;
     372                 :            :     }
     373         [ -  + ]:       4578 :   else if (c != '=')
     374                 :            :     {
     375                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     376                 :          0 :       return XDG_MIME_MAGIC_ERROR;
     377                 :            :     }
     378                 :            : 
     379                 :            :   /* Next two bytes determine how long the value is */
     380                 :       4578 :   matchlet->value_length = 0;
     381                 :       4578 :   c = getc_unlocked (magic_file);
     382         [ -  + ]:       4578 :   if (c == EOF)
     383                 :            :     {
     384                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     385                 :          0 :       return XDG_MIME_MAGIC_EOF;
     386                 :            :     }
     387                 :       4578 :   matchlet->value_length = c & 0xFF;
     388                 :       4578 :   matchlet->value_length = matchlet->value_length << 8;
     389                 :            : 
     390                 :       4578 :   c = getc_unlocked (magic_file);
     391         [ -  + ]:       4578 :   if (c == EOF)
     392                 :            :     {
     393                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     394                 :          0 :       return XDG_MIME_MAGIC_EOF;
     395                 :            :     }
     396                 :       4578 :   matchlet->value_length = matchlet->value_length + (c & 0xFF);
     397                 :            : 
     398                 :       4578 :   matchlet->value = malloc (matchlet->value_length);
     399                 :            : 
     400                 :            :   /* OOM */
     401         [ -  + ]:       4578 :   if (matchlet->value == NULL)
     402                 :            :     {
     403                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     404                 :          0 :       return XDG_MIME_MAGIC_ERROR;
     405                 :            :     }
     406                 :       4578 :   bytes_read = fread (matchlet->value, 1, matchlet->value_length, magic_file);
     407         [ -  + ]:       4578 :   if (bytes_read != matchlet->value_length)
     408                 :            :     {
     409                 :          0 :       _xdg_mime_magic_matchlet_free (matchlet);
     410         [ #  # ]:          0 :       if (feof (magic_file))
     411                 :          0 :         return XDG_MIME_MAGIC_EOF;
     412                 :            :       else
     413                 :          0 :         return XDG_MIME_MAGIC_ERROR;
     414                 :            :     }
     415                 :            : 
     416                 :       4578 :   c = getc_unlocked (magic_file);
     417         [ +  + ]:       4578 :   if (c == '&')
     418                 :            :     {
     419                 :         90 :       matchlet->mask = malloc (matchlet->value_length);
     420                 :            :       /* OOM */
     421         [ -  + ]:         90 :       if (matchlet->mask == NULL)
     422                 :            :         {
     423                 :          0 :           _xdg_mime_magic_matchlet_free (matchlet);
     424                 :          0 :           return XDG_MIME_MAGIC_ERROR;
     425                 :            :         }
     426                 :         90 :       bytes_read = fread (matchlet->mask, 1, matchlet->value_length, magic_file);
     427         [ -  + ]:         90 :       if (bytes_read != matchlet->value_length)
     428                 :            :         {
     429                 :          0 :           _xdg_mime_magic_matchlet_free (matchlet);
     430         [ #  # ]:          0 :           if (feof (magic_file))
     431                 :          0 :             return XDG_MIME_MAGIC_EOF;
     432                 :            :           else
     433                 :          0 :             return XDG_MIME_MAGIC_ERROR;
     434                 :            :         }
     435                 :         90 :       c = getc_unlocked (magic_file);
     436                 :            :     }
     437                 :            : 
     438         [ +  + ]:       4578 :   if (c == '~')
     439                 :            :     {
     440                 :         36 :       matchlet->word_size = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
     441         [ -  + ]:         36 :       if (end_of_file)
     442                 :            :         {
     443                 :          0 :           _xdg_mime_magic_matchlet_free (matchlet);
     444                 :          0 :           return XDG_MIME_MAGIC_EOF;
     445                 :            :         }
     446 [ +  - ][ +  - ]:         36 :       if (matchlet->word_size != 0 &&
         [ +  + ][ -  + ]
     447                 :         36 :           matchlet->word_size != 1 &&
     448                 :         36 :           matchlet->word_size != 2 &&
     449                 :         12 :           matchlet->word_size != 4)
     450                 :            :         {
     451                 :          0 :           _xdg_mime_magic_matchlet_free (matchlet);
     452                 :          0 :           return XDG_MIME_MAGIC_ERROR;
     453                 :            :         }
     454                 :         36 :       c = getc_unlocked (magic_file);
     455                 :            :     }
     456                 :            : 
     457         [ +  + ]:       4578 :   if (c == '+')
     458                 :            :     {
     459                 :        546 :       matchlet->range_length = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
     460         [ -  + ]:        546 :       if (end_of_file)
     461                 :            :         {
     462                 :          0 :           _xdg_mime_magic_matchlet_free (matchlet);
     463                 :          0 :           return XDG_MIME_MAGIC_EOF;
     464                 :            :         }
     465         [ -  + ]:        546 :       if (matchlet->range_length == -1)
     466                 :            :         {
     467                 :          0 :           _xdg_mime_magic_matchlet_free (matchlet);
     468                 :          0 :           return XDG_MIME_MAGIC_ERROR;
     469                 :            :         }
     470                 :        546 :       c = getc_unlocked (magic_file);
     471                 :            :     }
     472                 :            : 
     473                 :            : 
     474         [ +  - ]:       4578 :   if (c == '\n')
     475                 :            :     {
     476                 :            :       /* We clean up the matchlet, byte swapping if needed */
     477         [ +  + ]:       4578 :       if (matchlet->word_size > 1)
     478                 :            :         {
     479                 :            : #if LITTLE_ENDIAN
     480                 :            :           int i;
     481                 :            : #endif
     482         [ -  + ]:         36 :           if (matchlet->value_length % matchlet->word_size != 0)
     483                 :            :             {
     484                 :          0 :               _xdg_mime_magic_matchlet_free (matchlet);
     485                 :          0 :               return XDG_MIME_MAGIC_ERROR;
     486                 :            :             }
     487                 :            :           /* FIXME: need to get this defined in a <config.h> style file */
     488                 :            : #if LITTLE_ENDIAN
     489         [ +  + ]:         72 :           for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size)
     490                 :            :             {
     491         [ +  + ]:         36 :               if (matchlet->word_size == 2)
     492                 :         24 :                 *((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i)));
     493         [ +  - ]:         12 :               else if (matchlet->word_size == 4)
     494                 :         12 :                 *((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i)));
     495         [ -  + ]:         36 :               if (matchlet->mask)
     496                 :            :                 {
     497         [ #  # ]:          0 :                   if (matchlet->word_size == 2)
     498                 :          0 :                     *((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i)));
     499         [ #  # ]:          0 :                   else if (matchlet->word_size == 4)
     500                 :          0 :                     *((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i)));
     501                 :            : 
     502                 :            :                 }
     503                 :            :             }
     504                 :            : #endif
     505                 :            :         }
     506                 :            : 
     507                 :       4578 :       matchlet->next = match->matchlet;
     508                 :       4578 :       match->matchlet = matchlet;
     509                 :            : 
     510                 :            : 
     511                 :       4578 :       return XDG_MIME_MAGIC_MAGIC;
     512                 :            :     }
     513                 :            : 
     514                 :          0 :   _xdg_mime_magic_matchlet_free (matchlet);
     515         [ #  # ]:          0 :   if (c == EOF)
     516                 :          0 :     return XDG_MIME_MAGIC_EOF;
     517                 :            : 
     518                 :       6528 :   return XDG_MIME_MAGIC_ERROR;
     519                 :            : }
     520                 :            : 
     521                 :            : static int
     522                 :       1144 : _xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet,
     523                 :            :                                           const void           *data,
     524                 :            :                                           size_t                len)
     525                 :            : {
     526                 :            :   int i, j;
     527         [ +  + ]:      25431 :   for (i = matchlet->offset; i < matchlet->offset + matchlet->range_length; i++)
     528                 :            :     {
     529                 :      24294 :       int valid_matchlet = TRUE;
     530                 :            : 
     531         [ +  + ]:      24294 :       if (i + matchlet->value_length > len)
     532                 :          5 :         return FALSE;
     533                 :            : 
     534         [ +  + ]:      24289 :       if (matchlet->mask)
     535                 :            :         {
     536         [ +  - ]:         52 :           for (j = 0; j < matchlet->value_length; j++)
     537                 :            :             {
     538         [ +  - ]:         26 :               if ((matchlet->value[j] & matchlet->mask[j]) !=
     539                 :         26 :                   ((((unsigned char *) data)[j + i]) & matchlet->mask[j]))
     540                 :            :                 {
     541                 :         26 :                   valid_matchlet = FALSE;
     542                 :         26 :                   break;
     543                 :            :                 }
     544                 :            :             }
     545                 :            :         }
     546                 :            :       else
     547                 :            :         {
     548         [ +  + ]:      24747 :           for (j = 0; j <  matchlet->value_length; j++)
     549                 :            :             {
     550         [ +  + ]:      24745 :               if (matchlet->value[j] != ((unsigned char *) data)[j + i])
     551                 :            :                 {
     552                 :      24261 :                   valid_matchlet = FALSE;
     553                 :      24261 :                   break;
     554                 :            :                 }
     555                 :            :             }
     556                 :            :         }
     557         [ +  + ]:      24289 :       if (valid_matchlet)
     558                 :          2 :         return TRUE;
     559                 :            :     }
     560                 :       1144 :   return FALSE;
     561                 :            : }
     562                 :            : 
     563                 :            : static int
     564                 :        650 : _xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet,
     565                 :            :                                         const void           *data,
     566                 :            :                                         size_t                len,
     567                 :            :                                         int                   indent)
     568                 :            : {
     569 [ +  + ][ +  - ]:       1792 :   while ((matchlet != NULL) && (matchlet->indent == indent))
     570                 :            :     {
     571         [ +  + ]:       1144 :       if (_xdg_mime_magic_matchlet_compare_to_data (matchlet, data, len))
     572                 :            :         {
     573 [ +  + ][ +  - ]:          2 :           if ((matchlet->next == NULL) ||
     574                 :          1 :               (matchlet->next->indent <= indent))
     575                 :          2 :             return TRUE;
     576                 :            : 
     577         [ #  # ]:          0 :           if (_xdg_mime_magic_matchlet_compare_level (matchlet->next,
     578                 :            :                                                       data,
     579                 :            :                                                       len,
     580                 :            :                                                       indent + 1))
     581                 :          0 :             return TRUE;
     582                 :            :         }
     583                 :            : 
     584                 :            :       do
     585                 :            :         {
     586                 :       1522 :           matchlet = matchlet->next;
     587                 :            :         }
     588 [ +  + ][ +  + ]:       1522 :       while (matchlet && matchlet->indent > indent);
     589                 :            :     }
     590                 :            : 
     591                 :        650 :   return FALSE;
     592                 :            : }
     593                 :            : 
     594                 :            : static int
     595                 :        650 : _xdg_mime_magic_match_compare_to_data (XdgMimeMagicMatch *match,
     596                 :            :                                        const void        *data,
     597                 :            :                                        size_t             len)
     598                 :            : {
     599                 :        650 :   return _xdg_mime_magic_matchlet_compare_level (match->matchlet, data, len, 0);
     600                 :            : }
     601                 :            : 
     602                 :            : static void
     603                 :       1950 : _xdg_mime_magic_insert_match (XdgMimeMagic      *mime_magic,
     604                 :            :                               XdgMimeMagicMatch *match)
     605                 :            : {
     606                 :            :   XdgMimeMagicMatch *list;
     607                 :            : 
     608         [ +  + ]:       1950 :   if (mime_magic->match_list == NULL)
     609                 :            :     {
     610                 :          6 :       mime_magic->match_list = match;
     611                 :          6 :       return;
     612                 :            :     }
     613                 :            : 
     614         [ -  + ]:       1944 :   if (match->priority > mime_magic->match_list->priority)
     615                 :            :     {
     616                 :          0 :       match->next = mime_magic->match_list;
     617                 :          0 :       mime_magic->match_list = match;
     618                 :          0 :       return;
     619                 :            :     }
     620                 :            : 
     621                 :       1944 :   list = mime_magic->match_list;
     622         [ +  + ]:     315900 :   while (list->next != NULL)
     623                 :            :     {
     624         [ -  + ]:     313956 :       if (list->next->priority < match->priority)
     625                 :            :         {
     626                 :          0 :           match->next = list->next;
     627                 :          0 :           list->next = match;
     628                 :          0 :           return;
     629                 :            :         }
     630                 :     313956 :       list = list->next;
     631                 :            :     }
     632                 :       1944 :   list->next = match;
     633                 :       1950 :   match->next = NULL;
     634                 :            : }
     635                 :            : 
     636                 :            : XdgMimeMagic *
     637                 :          6 : _xdg_mime_magic_new (void)
     638                 :            : {
     639                 :          6 :   return calloc (1, sizeof (XdgMimeMagic));
     640                 :            : }
     641                 :            : 
     642                 :            : void
     643                 :          6 : _xdg_mime_magic_free (XdgMimeMagic *mime_magic)
     644                 :            : {
     645         [ +  - ]:          6 :   if (mime_magic) {
     646                 :          6 :     _xdg_mime_magic_match_free (mime_magic->match_list);
     647                 :          6 :     free (mime_magic);
     648                 :            :   }
     649                 :          6 : }
     650                 :            : 
     651                 :            : int
     652                 :          0 : _xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic)
     653                 :            : {
     654                 :          0 :   return mime_magic->max_extent;
     655                 :            : }
     656                 :            : 
     657                 :            : const char *
     658                 :          2 : _xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic,
     659                 :            :                              const void   *data,
     660                 :            :                              size_t        len,
     661                 :            :                              const char   *mime_types[],
     662                 :            :                              int           n_mime_types)
     663                 :            : {
     664                 :            :   XdgMimeMagicMatch *match;
     665                 :            :   const char *mime_type;
     666                 :            :   int n;
     667                 :            :   int priority;
     668                 :            :   int had_match;
     669                 :            : 
     670                 :          2 :   mime_type = NULL;
     671                 :          2 :   priority = 0;
     672                 :          2 :   had_match = 0;
     673         [ +  + ]:        652 :   for (match = mime_magic->match_list; match; match = match->next)
     674                 :            :     {
     675         [ +  + ]:        650 :       if (_xdg_mime_magic_match_compare_to_data (match, data, len))
     676                 :            :         {
     677 [ -  + ][ #  # ]:          2 :           if (!had_match || match->priority > priority ||
           [ #  #  #  # ]
     678                 :          0 :               (mime_type != NULL && _xdg_mime_mime_type_subclass (match->mime_type, mime_type)))
     679                 :            :             {
     680                 :          2 :               mime_type = match->mime_type;
     681                 :          2 :               priority = match->priority;
     682                 :            :             }
     683         [ #  # ]:          0 :           else if (had_match && match->priority == priority &&
           [ #  #  #  # ]
     684                 :          0 :                    !_xdg_mime_mime_type_subclass (mime_type, match->mime_type))
     685                 :            :             /* multiple unrelated patterns with the same priority matched,
     686                 :            :              * so we can't tell what type this is. */
     687                 :          0 :             mime_type = NULL;
     688                 :            : 
     689                 :          2 :           had_match = 1;
     690                 :            :         }
     691                 :            :       else 
     692                 :            :         {
     693         [ -  + ]:        648 :           for (n = 0; n < n_mime_types; n++)
     694                 :            :             {
     695   [ #  #  #  # ]:          0 :               if (mime_types[n] && 
     696                 :          0 :                   _xdg_mime_mime_type_equal (mime_types[n], match->mime_type))
     697                 :          0 :                 mime_types[n] = NULL;
     698                 :            :             }
     699                 :            :         }
     700                 :            :     }
     701                 :            : 
     702         [ -  + ]:          2 :   if (mime_type == NULL)
     703                 :            :     {
     704         [ #  # ]:          0 :       for (n = 0; n < n_mime_types; n++)
     705                 :            :         {
     706         [ #  # ]:          0 :           if (mime_types[n])
     707                 :          0 :             mime_type = mime_types[n];
     708                 :            :         }
     709                 :            :     }
     710                 :            : 
     711                 :          2 :   return mime_type;
     712                 :            : }
     713                 :            : 
     714                 :            : static void
     715                 :          6 : _xdg_mime_update_mime_magic_extents (XdgMimeMagic *mime_magic)
     716                 :            : {
     717                 :            :   XdgMimeMagicMatch *match;
     718                 :          6 :   int max_extent = 0;
     719                 :            : 
     720         [ +  + ]:       1956 :   for (match = mime_magic->match_list; match; match = match->next)
     721                 :            :     {
     722                 :            :       XdgMimeMagicMatchlet *matchlet;
     723                 :            : 
     724         [ +  + ]:       6528 :       for (matchlet = match->matchlet; matchlet; matchlet = matchlet->next)
     725                 :            :         {
     726                 :            :           int extent;
     727                 :            : 
     728                 :       4578 :           extent = matchlet->value_length + matchlet->offset + matchlet->range_length;
     729         [ +  + ]:       4578 :           if (max_extent < extent)
     730                 :         30 :             max_extent = extent;
     731                 :            :         }
     732                 :            :     }
     733                 :            : 
     734                 :          6 :   mime_magic->max_extent = max_extent;
     735                 :          6 : }
     736                 :            : 
     737                 :            : static XdgMimeMagicMatchlet *
     738                 :       1950 : _xdg_mime_magic_matchlet_mirror (XdgMimeMagicMatchlet *matchlets)
     739                 :            : {
     740                 :            :   XdgMimeMagicMatchlet *new_list;
     741                 :            :   XdgMimeMagicMatchlet *tmp;
     742                 :            : 
     743 [ +  - ][ +  + ]:       1950 :   if ((matchlets == NULL) || (matchlets->next == NULL))
     744                 :       1020 :     return matchlets;
     745                 :            : 
     746                 :        930 :   new_list = NULL;
     747                 :        930 :   tmp = matchlets;
     748         [ +  + ]:       4488 :   while (tmp != NULL)
     749                 :            :     {
     750                 :            :       XdgMimeMagicMatchlet *matchlet;
     751                 :            : 
     752                 :       3558 :       matchlet = tmp;
     753                 :       3558 :       tmp = tmp->next;
     754                 :       3558 :       matchlet->next = new_list;
     755                 :       3558 :       new_list = matchlet;
     756                 :            :     }
     757                 :            : 
     758                 :       1950 :   return new_list;
     759                 :            : 
     760                 :            : }
     761                 :            : 
     762                 :            : static void
     763                 :          6 : _xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic,
     764                 :            :                                  FILE         *magic_file)
     765                 :            : {
     766                 :            :   XdgMimeMagicState state;
     767                 :          6 :   XdgMimeMagicMatch *match = NULL; /* Quiet compiler */
     768                 :            : 
     769                 :          6 :   state = XDG_MIME_MAGIC_SECTION;
     770                 :            : 
     771         [ +  + ]:       8484 :   while (state != XDG_MIME_MAGIC_EOF)
     772                 :            :     {
     773   [ +  +  -  - ]:       8478 :       switch (state)
     774                 :            :         {
     775                 :            :         case XDG_MIME_MAGIC_SECTION:
     776                 :       1950 :           match = _xdg_mime_magic_match_new ();
     777                 :       1950 :           state = _xdg_mime_magic_parse_header (magic_file, match);
     778   [ +  -  -  + ]:       1950 :           if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
     779                 :          0 :             _xdg_mime_magic_match_free (match);
     780                 :       1950 :           break;
     781                 :            :         case XDG_MIME_MAGIC_MAGIC:
     782                 :       6528 :           state = _xdg_mime_magic_parse_magic_line (magic_file, match);
     783   [ +  +  +  + ]:       8478 :           if (state == XDG_MIME_MAGIC_SECTION ||
                 [ +  - ]
     784                 :          6 :               (state == XDG_MIME_MAGIC_EOF && match->mime_type))
     785                 :            :             {
     786                 :       1950 :               match->matchlet = _xdg_mime_magic_matchlet_mirror (match->matchlet);
     787                 :       1950 :               _xdg_mime_magic_insert_match (mime_magic, match);
     788                 :            :             }
     789 [ +  - ][ -  + ]:       4578 :           else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
     790                 :          0 :             _xdg_mime_magic_match_free (match);
     791                 :       6528 :           break;
     792                 :            :         case XDG_MIME_MAGIC_ERROR:
     793                 :          0 :           state = _xdg_mime_magic_parse_error (magic_file);
     794                 :          0 :           break;
     795                 :            :         case XDG_MIME_MAGIC_EOF:
     796                 :            :         default:
     797                 :            :           /* Make the compiler happy */
     798                 :          0 :           assert (0);
     799                 :            :         }
     800                 :            :     }
     801                 :          6 :   _xdg_mime_update_mime_magic_extents (mime_magic);
     802                 :          6 : }
     803                 :            : 
     804                 :            : void
     805                 :          6 : _xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic,
     806                 :            :                                 const char   *file_name)
     807                 :            : {
     808                 :            :   FILE *magic_file;
     809                 :            :   char header[12];
     810                 :            : 
     811                 :          6 :   magic_file = fopen (file_name, "r");
     812                 :            : 
     813         [ -  + ]:          6 :   if (magic_file == NULL)
     814                 :          0 :     return;
     815                 :            : 
     816         [ +  - ]:          6 :   if (fread (header, 1, 12, magic_file) == 12)
     817                 :            :     {
     818         [ +  - ]:          6 :       if (memcmp ("MIME-Magic\0\n", header, 12) == 0)
     819                 :          6 :         _xdg_mime_magic_read_magic_file (mime_magic, magic_file);
     820                 :            :     }
     821                 :            : 
     822                 :          6 :   fclose (magic_file);
     823                 :            : }

Generated by: LCOV version 1.8