1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* xdgmimealias.c: Private file. mmappable caches for mime data
4 * More info can be found at http://www.freedesktop.org/standards/
6 * Copyright (C) 2005 Matthias Clasen <mclasen@redhat.com>
8 * Licensed under the Academic Free License version 2.0
9 * Or under the following terms:
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
37 #include <netinet/in.h> /* for ntohl/ntohs */
42 #warning Building xdgmime without MMAP support. Binary "mime.info" cache files will not be used.
46 #include <sys/types.h>
48 #include "xdgmimecache.h"
49 #include "xdgmimeint.h"
52 #define MAX(a,b) ((a) > (b) ? (a) : (b))
68 #define MAP_FAILED ((void *) -1)
71 #define MAJOR_VERSION 1
72 #define MINOR_VERSION_MIN 1
73 #define MINOR_VERSION_MAX 2
84 #define GET_UINT16(cache,offset) (ntohs(*(xdg_uint16_t*)((cache) + (offset))))
85 #define GET_UINT32(cache,offset) (ntohl(*(xdg_uint32_t*)((cache) + (offset))))
88 _xdg_mime_cache_ref (XdgMimeCache
*cache
)
95 _xdg_mime_cache_unref (XdgMimeCache
*cache
)
99 if (cache
->ref_count
== 0)
102 munmap (cache
->buffer
, cache
->size
);
109 _xdg_mime_cache_new_from_file (const char *file_name
)
111 XdgMimeCache
*cache
= NULL
;
119 /* Open the file and map it into memory */
121 fd
= open (file_name
, O_RDONLY
|_O_BINARY
, 0);
122 while (fd
== -1 && errno
== EINTR
);
127 if (fstat (fd
, &st
) < 0 || st
.st_size
< 4)
130 buffer
= (char *) mmap (NULL
, st
.st_size
, PROT_READ
, MAP_SHARED
, fd
, 0);
132 if (buffer
== MAP_FAILED
)
135 minor
= GET_UINT16 (buffer
, 2);
137 if (GET_UINT16 (buffer
, 0) != MAJOR_VERSION
||
138 (minor
< MINOR_VERSION_MIN
||
139 minor
> MINOR_VERSION_MAX
))
141 munmap (buffer
, st
.st_size
);
146 cache
= (XdgMimeCache
*) malloc (sizeof (XdgMimeCache
));
147 cache
->minor
= minor
;
148 cache
->ref_count
= 1;
149 cache
->buffer
= buffer
;
150 cache
->size
= st
.st_size
;
156 #else /* HAVE_MMAP */
157 cache
= (XdgMimeCache
*) malloc (sizeof (XdgMimeCache
));
159 cache
->ref_count
= 1;
160 cache
->buffer
= NULL
;
162 #endif /* HAVE_MMAP */
168 cache_magic_matchlet_compare_to_data (XdgMimeCache
*cache
,
173 xdg_uint32_t range_start
= GET_UINT32 (cache
->buffer
, offset
);
174 xdg_uint32_t range_length
= GET_UINT32 (cache
->buffer
, offset
+ 4);
175 xdg_uint32_t data_length
= GET_UINT32 (cache
->buffer
, offset
+ 12);
176 xdg_uint32_t data_offset
= GET_UINT32 (cache
->buffer
, offset
+ 16);
177 xdg_uint32_t mask_offset
= GET_UINT32 (cache
->buffer
, offset
+ 20);
181 for (i
= range_start
; i
< range_start
+ range_length
; i
++)
183 int valid_matchlet
= TRUE
;
185 if (i
+ data_length
> len
)
190 for (j
= 0; j
< data_length
; j
++)
192 if ((((unsigned char *)cache
->buffer
)[data_offset
+ j
] & ((unsigned char *)cache
->buffer
)[mask_offset
+ j
]) !=
193 ((((unsigned char *) data
)[j
+ i
]) & ((unsigned char *)cache
->buffer
)[mask_offset
+ j
]))
195 valid_matchlet
= FALSE
;
202 for (j
= 0; j
< data_length
; j
++)
204 if (((unsigned char *)cache
->buffer
)[data_offset
+ j
] != ((unsigned char *) data
)[j
+ i
])
206 valid_matchlet
= FALSE
;
220 cache_magic_matchlet_compare (XdgMimeCache
*cache
,
225 xdg_uint32_t n_children
= GET_UINT32 (cache
->buffer
, offset
+ 24);
226 xdg_uint32_t child_offset
= GET_UINT32 (cache
->buffer
, offset
+ 28);
230 if (cache_magic_matchlet_compare_to_data (cache
, offset
, data
, len
))
235 for (i
= 0; i
< n_children
; i
++)
237 if (cache_magic_matchlet_compare (cache
, child_offset
+ 32 * i
,
247 cache_magic_compare_to_data (XdgMimeCache
*cache
,
253 xdg_uint32_t priority
= GET_UINT32 (cache
->buffer
, offset
);
254 xdg_uint32_t mimetype_offset
= GET_UINT32 (cache
->buffer
, offset
+ 4);
255 xdg_uint32_t n_matchlets
= GET_UINT32 (cache
->buffer
, offset
+ 8);
256 xdg_uint32_t matchlet_offset
= GET_UINT32 (cache
->buffer
, offset
+ 12);
260 for (i
= 0; i
< n_matchlets
; i
++)
262 if (cache_magic_matchlet_compare (cache
, matchlet_offset
+ i
* 32,
267 return cache
->buffer
+ mimetype_offset
;
275 cache_magic_lookup_data (XdgMimeCache
*cache
,
279 const char *mime_types
[],
282 xdg_uint32_t list_offset
;
283 xdg_uint32_t n_entries
;
290 list_offset
= GET_UINT32 (cache
->buffer
, 24);
291 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
292 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 8);
294 for (j
= 0; j
< n_entries
; j
++)
298 match
= cache_magic_compare_to_data (cache
, offset
+ 16 * j
,
304 xdg_uint32_t mimetype_offset
;
305 const char *non_match
;
307 mimetype_offset
= GET_UINT32 (cache
->buffer
, offset
+ 16 * j
+ 4);
308 non_match
= cache
->buffer
+ mimetype_offset
;
310 for (n
= 0; n
< n_mime_types
; n
++)
313 _xdg_mime_mime_type_equal (mime_types
[n
], non_match
))
314 mime_types
[n
] = NULL
;
323 cache_alias_lookup (const char *alias
)
326 int i
, min
, max
, mid
, cmp
;
328 for (i
= 0; _caches
[i
]; i
++)
330 XdgMimeCache
*cache
= _caches
[i
];
331 xdg_uint32_t list_offset
;
332 xdg_uint32_t n_entries
;
335 if (cache
->buffer
== NULL
)
338 list_offset
= GET_UINT32 (cache
->buffer
, 4);
339 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
345 mid
= (min
+ max
) / 2;
347 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * mid
);
348 ptr
= cache
->buffer
+ offset
;
349 cmp
= strcmp (ptr
, alias
);
357 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * mid
+ 4);
358 return cache
->buffer
+ offset
;
372 cache_glob_lookup_literal (const char *file_name
,
373 const char *mime_types
[],
375 int case_sensitive_check
)
378 int i
, min
, max
, mid
, cmp
;
380 for (i
= 0; _caches
[i
]; i
++)
382 XdgMimeCache
*cache
= _caches
[i
];
383 xdg_uint32_t list_offset
;
384 xdg_uint32_t n_entries
;
387 if (cache
->buffer
== NULL
)
390 list_offset
= GET_UINT32 (cache
->buffer
, 12);
391 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
397 mid
= (min
+ max
) / 2;
399 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 12 * mid
);
400 ptr
= cache
->buffer
+ offset
;
401 cmp
= strcmp (ptr
, file_name
);
409 int weight
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 12 * mid
+ 8);
410 int case_sensitive
= weight
& 0x100;
411 weight
= weight
& 0xff;
413 if (case_sensitive_check
|| !case_sensitive
)
415 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 12 * mid
+ 4);
416 mime_types
[0] = (const char *)(cache
->buffer
+ offset
);
429 cache_glob_lookup_fnmatch (const char *file_name
,
430 MimeWeight mime_types
[],
433 const char *mime_type
;
439 for (i
= 0; _caches
[i
]; i
++)
441 XdgMimeCache
*cache
= _caches
[i
];
443 xdg_uint32_t list_offset
;
444 xdg_uint32_t n_entries
;
446 if (cache
->buffer
== NULL
)
449 list_offset
= GET_UINT32 (cache
->buffer
, 20);
450 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
452 for (j
= 0; j
< n_entries
&& n
< n_mime_types
; j
++)
454 xdg_uint32_t offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 12 * j
);
455 xdg_uint32_t mimetype_offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 12 * j
+ 4);
456 int weight
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 12 * j
+ 8);
457 weight
= weight
& 0xff;
458 ptr
= cache
->buffer
+ offset
;
459 mime_type
= cache
->buffer
+ mimetype_offset
;
461 /* FIXME: Not UTF-8 safe */
462 if (fnmatch (ptr
, file_name
, 0) == 0)
464 mime_types
[n
].mime
= mime_type
;
465 mime_types
[n
].weight
= weight
;
470 if (n
== n_mime_types
)
478 cache_glob_node_lookup_suffix (XdgMimeCache
*cache
,
479 xdg_uint32_t n_entries
,
481 const char *file_name
,
483 int case_sensitive_check
,
484 MimeWeight mime_types
[],
487 xdg_unichar_t character
;
488 xdg_unichar_t match_char
;
489 xdg_uint32_t mimetype_offset
;
490 xdg_uint32_t n_children
;
491 xdg_uint32_t child_offset
;
495 int min
, max
, mid
, n
, i
;
497 character
= file_name
[len
- 1];
499 assert (character
!= 0);
505 mid
= (min
+ max
) / 2;
506 match_char
= GET_UINT32 (cache
->buffer
, offset
+ 12 * mid
);
507 if (match_char
< character
)
509 else if (match_char
> character
)
515 n_children
= GET_UINT32 (cache
->buffer
, offset
+ 12 * mid
+ 4);
516 child_offset
= GET_UINT32 (cache
->buffer
, offset
+ 12 * mid
+ 8);
520 n
= cache_glob_node_lookup_suffix (cache
,
521 n_children
, child_offset
,
523 case_sensitive_check
,
530 while (n
< n_mime_types
&& i
< n_children
)
532 match_char
= GET_UINT32 (cache
->buffer
, child_offset
+ 12 * i
);
536 mimetype_offset
= GET_UINT32 (cache
->buffer
, child_offset
+ 12 * i
+ 4);
537 weight
= GET_UINT32 (cache
->buffer
, child_offset
+ 12 * i
+ 8);
538 case_sensitive
= weight
& 0x100;
539 weight
= weight
& 0xff;
541 if (case_sensitive_check
|| !case_sensitive
)
543 mime_types
[n
].mime
= cache
->buffer
+ mimetype_offset
;
544 mime_types
[n
].weight
= weight
;
557 cache_glob_lookup_suffix (const char *file_name
,
560 MimeWeight mime_types
[],
566 for (i
= 0; _caches
[i
]; i
++)
568 XdgMimeCache
*cache
= _caches
[i
];
570 xdg_uint32_t list_offset
;
571 xdg_uint32_t n_entries
;
574 if (cache
->buffer
== NULL
)
577 list_offset
= GET_UINT32 (cache
->buffer
, 16);
578 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
579 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4);
581 n
+= cache_glob_node_lookup_suffix (cache
,
587 if (n
== n_mime_types
)
594 static int compare_mime_weight (const void *a
, const void *b
)
596 const MimeWeight
*aa
= (const MimeWeight
*)a
;
597 const MimeWeight
*bb
= (const MimeWeight
*)b
;
599 return bb
->weight
- aa
->weight
;
602 #define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z')
604 ascii_tolower (const char *str
)
608 lower
= strdup (str
);
613 *p
++ = ISUPPER (c
) ? c
- 'A' + 'a' : c
;
619 filter_out_dupes (MimeWeight mimes
[], int n_mimes
)
626 for (i
= 0; i
< last
; i
++)
631 if (strcmp (mimes
[i
].mime
, mimes
[j
].mime
) == 0)
633 mimes
[i
].weight
= MAX (mimes
[i
].weight
, mimes
[j
].weight
);
635 mimes
[j
].mime
= mimes
[last
].mime
;
636 mimes
[j
].weight
= mimes
[last
].weight
;
647 cache_glob_lookup_file_name (const char *file_name
,
648 const char *mime_types
[],
652 MimeWeight mimes
[10];
658 assert (file_name
!= NULL
&& n_mime_types
> 0);
660 /* First, check the literals */
662 lower_case
= ascii_tolower (file_name
);
664 n
= cache_glob_lookup_literal (lower_case
, mime_types
, n_mime_types
, FALSE
);
671 n
= cache_glob_lookup_literal (file_name
, mime_types
, n_mime_types
, TRUE
);
678 len
= strlen (file_name
);
679 n
= cache_glob_lookup_suffix (lower_case
, len
, FALSE
, mimes
, n_mimes
);
681 n
+= cache_glob_lookup_suffix (file_name
, len
, TRUE
, mimes
+ n
, n_mimes
- n
);
685 /* Last, try fnmatch */
687 n
+= cache_glob_lookup_fnmatch (file_name
, mimes
+ n
, n_mimes
- n
);
689 n
= filter_out_dupes (mimes
, n
);
691 qsort (mimes
, n
, sizeof (MimeWeight
), compare_mime_weight
);
693 if (n_mime_types
< n
)
696 for (i
= 0; i
< n
; i
++)
697 mime_types
[i
] = mimes
[i
].mime
;
703 _xdg_mime_cache_get_max_buffer_extents (void)
706 xdg_uint32_t max_extent
;
710 for (i
= 0; _caches
[i
]; i
++)
712 XdgMimeCache
*cache
= _caches
[i
];
714 if (cache
->buffer
== NULL
)
717 offset
= GET_UINT32 (cache
->buffer
, 24);
718 max_extent
= MAX (max_extent
, GET_UINT32 (cache
->buffer
, offset
+ 4));
725 cache_get_mime_type_for_data (const void *data
,
728 const char *mime_types
[],
731 const char *mime_type
;
736 for (i
= 0; _caches
[i
]; i
++)
738 XdgMimeCache
*cache
= _caches
[i
];
743 if (cache
->buffer
== NULL
)
746 match
= cache_magic_lookup_data (cache
, data
, len
, &prio
,
747 mime_types
, n_mime_types
);
756 *result_prio
= priority
;
761 for (n
= 0; n
< n_mime_types
; n
++)
764 return mime_types
[n
];
771 _xdg_mime_cache_get_mime_type_for_data (const void *data
,
775 return cache_get_mime_type_for_data (data
, len
, result_prio
, NULL
, 0);
778 #ifdef NOT_USED_IN_GIO
781 _xdg_mime_cache_get_mime_type_for_file (const char *file_name
,
782 struct stat
*statbuf
)
784 const char *mime_type
;
785 const char *mime_types
[10];
791 const char *base_name
;
794 if (file_name
== NULL
)
797 if (! _xdg_utf8_validate (file_name
))
800 base_name
= _xdg_get_base_name (file_name
);
801 n
= cache_glob_lookup_file_name (base_name
, mime_types
, 10);
804 return mime_types
[0];
808 if (stat (file_name
, &buf
) != 0)
809 return XDG_MIME_TYPE_UNKNOWN
;
814 if (statbuf
->st_size
== 0)
815 return XDG_MIME_TYPE_EMPTY
;
817 if (!S_ISREG (statbuf
->st_mode
))
818 return XDG_MIME_TYPE_UNKNOWN
;
820 /* FIXME: Need to make sure that max_extent isn't totally broken. This could
821 * be large and need getting from a stream instead of just reading it all
823 max_extent
= _xdg_mime_cache_get_max_buffer_extents ();
824 data
= malloc (max_extent
);
826 return XDG_MIME_TYPE_UNKNOWN
;
828 file
= fopen (file_name
, "r");
832 return XDG_MIME_TYPE_UNKNOWN
;
835 bytes_read
= fread (data
, 1, max_extent
, file
);
840 return XDG_MIME_TYPE_UNKNOWN
;
843 mime_type
= cache_get_mime_type_for_data (data
, bytes_read
, NULL
,
847 mime_type
= _xdg_binary_or_text_fallback(data
, bytes_read
);
856 _xdg_mime_cache_get_mime_type_from_file_name (const char *file_name
)
858 const char *mime_type
;
860 if (cache_glob_lookup_file_name (file_name
, &mime_type
, 1))
863 return XDG_MIME_TYPE_UNKNOWN
;
869 _xdg_mime_cache_get_mime_types_from_file_name (const char *file_name
,
870 const char *mime_types
[],
873 return cache_glob_lookup_file_name (file_name
, mime_types
, n_mime_types
);
878 ends_with (const char *str
,
884 length
= strlen (str
);
885 suffix_length
= strlen (suffix
);
886 if (length
< suffix_length
)
889 if (strcmp (str
+ length
- suffix_length
, suffix
) == 0)
896 is_super_type (const char *mime
)
898 return ends_with (mime
, "/*");
903 _xdg_mime_cache_mime_type_subclass (const char *mime
,
906 const char *umime
, *ubase
;
908 int i
, j
, min
, max
, med
, cmp
;
910 umime
= _xdg_mime_cache_unalias_mime_type (mime
);
911 ubase
= _xdg_mime_cache_unalias_mime_type (base
);
913 if (strcmp (umime
, ubase
) == 0)
916 /* We really want to handle text/ * in GtkFileFilter, so we just
917 * turn on the supertype matching
920 /* Handle supertypes */
921 if (is_super_type (ubase
) &&
922 xdg_mime_media_type_equal (umime
, ubase
))
926 /* Handle special cases text/plain and application/octet-stream */
927 if (strcmp (ubase
, "text/plain") == 0 &&
928 strncmp (umime
, "text/", 5) == 0)
931 if (strcmp (ubase
, "application/octet-stream") == 0 &&
932 strncmp (umime
, "inode/", 6) != 0)
935 for (i
= 0; _caches
[i
]; i
++)
937 XdgMimeCache
*cache
= _caches
[i
];
938 xdg_uint32_t list_offset
;
939 xdg_uint32_t n_entries
;
940 xdg_uint32_t offset
, n_parents
, parent_offset
;
942 if (cache
->buffer
== NULL
)
945 list_offset
= GET_UINT32 (cache
->buffer
, 8);
946 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
954 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * med
);
955 cmp
= strcmp (cache
->buffer
+ offset
, umime
);
962 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * med
+ 4);
963 n_parents
= GET_UINT32 (cache
->buffer
, offset
);
965 for (j
= 0; j
< n_parents
; j
++)
967 parent_offset
= GET_UINT32 (cache
->buffer
, offset
+ 4 + 4 * j
);
968 if (_xdg_mime_cache_mime_type_subclass (cache
->buffer
+ parent_offset
, ubase
))
981 _xdg_mime_cache_unalias_mime_type (const char *mime
)
985 lookup
= cache_alias_lookup (mime
);
994 _xdg_mime_cache_list_mime_parents (const char *mime
)
997 char *all_parents
[128]; /* we'll stop at 128 */
1000 mime
= xdg_mime_unalias_mime_type (mime
);
1003 for (i
= 0; _caches
[i
]; i
++)
1005 XdgMimeCache
*cache
= _caches
[i
];
1006 xdg_uint32_t list_offset
;
1007 xdg_uint32_t n_entries
;
1009 if (cache
->buffer
== NULL
)
1012 list_offset
= GET_UINT32 (cache
->buffer
, 8);
1013 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
1015 for (j
= 0; j
< n_entries
; j
++)
1017 xdg_uint32_t mimetype_offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * j
);
1018 xdg_uint32_t parents_offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * j
+ 4);
1020 if (strcmp (cache
->buffer
+ mimetype_offset
, mime
) == 0)
1022 xdg_uint32_t parent_mime_offset
;
1023 xdg_uint32_t n_parents
= GET_UINT32 (cache
->buffer
, parents_offset
);
1025 for (k
= 0; k
< n_parents
&& p
< 127; k
++)
1027 parent_mime_offset
= GET_UINT32 (cache
->buffer
, parents_offset
+ 4 + 4 * k
);
1029 /* Don't add same parent multiple times.
1030 * This can happen for instance if the same type is listed in multiple directories
1032 for (l
= 0; l
< p
; l
++)
1034 if (strcmp (all_parents
[l
], cache
->buffer
+ parent_mime_offset
) == 0)
1039 all_parents
[p
++] = cache
->buffer
+ parent_mime_offset
;
1046 all_parents
[p
++] = NULL
;
1048 result
= (char **) malloc (p
* sizeof (char *));
1049 memcpy (result
, all_parents
, p
* sizeof (char *));
1055 cache_lookup_icon (const char *mime
, int header
)
1058 int i
, min
, max
, mid
, cmp
;
1060 for (i
= 0; _caches
[i
]; i
++)
1062 XdgMimeCache
*cache
= _caches
[i
];
1063 xdg_uint32_t list_offset
;
1064 xdg_uint32_t n_entries
;
1065 xdg_uint32_t offset
;
1067 if (cache
->buffer
== NULL
)
1070 list_offset
= GET_UINT32 (cache
->buffer
, header
);
1071 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
1074 max
= n_entries
- 1;
1077 mid
= (min
+ max
) / 2;
1079 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * mid
);
1080 ptr
= cache
->buffer
+ offset
;
1081 cmp
= strcmp (ptr
, mime
);
1089 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4 + 8 * mid
+ 4);
1090 return cache
->buffer
+ offset
;
1099 _xdg_mime_cache_get_generic_icon (const char *mime
)
1101 return cache_lookup_icon (mime
, 36);
1105 _xdg_mime_cache_get_icon (const char *mime
)
1107 return cache_lookup_icon (mime
, 32);
1110 #ifdef NOT_USED_IN_GIO
1113 dump_glob_node (XdgMimeCache
*cache
,
1114 xdg_uint32_t offset
,
1117 xdg_unichar_t character
;
1118 xdg_uint32_t mime_offset
;
1119 xdg_uint32_t n_children
;
1120 xdg_uint32_t child_offset
;
1123 character
= GET_UINT32 (cache
->buffer
, offset
);
1124 mime_offset
= GET_UINT32 (cache
->buffer
, offset
+ 4);
1125 n_children
= GET_UINT32 (cache
->buffer
, offset
+ 8);
1126 child_offset
= GET_UINT32 (cache
->buffer
, offset
+ 12);
1127 for (i
= 0; i
< depth
; i
++)
1129 printf ("%c", character
);
1131 printf (" - %s", cache
->buffer
+ mime_offset
);
1135 for (i
= 0; i
< n_children
; i
++)
1136 dump_glob_node (cache
, child_offset
+ 20 * i
, depth
+ 1);
1141 _xdg_mime_cache_glob_dump (void)
1144 for (i
= 0; _caches
[i
]; i
++)
1146 XdgMimeCache
*cache
= _caches
[i
];
1147 xdg_uint32_t list_offset
;
1148 xdg_uint32_t n_entries
;
1149 xdg_uint32_t offset
;
1151 if (cache
->buffer
== NULL
)
1154 list_offset
= GET_UINT32 (cache
->buffer
, 16);
1155 n_entries
= GET_UINT32 (cache
->buffer
, list_offset
);
1156 offset
= GET_UINT32 (cache
->buffer
, list_offset
+ 4);
1157 for (j
= 0; j
< n_entries
; j
++)
1158 dump_glob_node (cache
, offset
+ 20 * j
, 0);