]> granicus.if.org Git - imagemagick/blob - MagickCore/magic.c
8b65d5efa68cd731e62783be53a7484af7d92e80
[imagemagick] / MagickCore / magic.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                    M   M   AAA    GGGG  IIIII   CCCC                        %
7 %                    MM MM  A   A  G        I    C                            %
8 %                    M M M  AAAAA  G GGG    I    C                            %
9 %                    M   M  A   A  G   G    I    C                            %
10 %                    M   M  A   A   GGGG  IIIII   CCCC                        %
11 %                                                                             %
12 %                                                                             %
13 %                      MagickCore Image Magic Methods                         %
14 %                                                                             %
15 %                              Software Design                                %
16 %                              Bob Friesenhahn                                %
17 %                                 July 2000                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/client.h"
45 #include "MagickCore/configure.h"
46 #include "MagickCore/configure-private.h"
47 #include "MagickCore/exception.h"
48 #include "MagickCore/exception-private.h"
49 #include "MagickCore/linked-list.h"
50 #include "MagickCore/magic.h"
51 #include "MagickCore/magic-private.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/memory-private.h"
54 #include "MagickCore/semaphore.h"
55 #include "MagickCore/string_.h"
56 #include "MagickCore/string-private.h"
57 #include "MagickCore/token.h"
58 #include "MagickCore/utility.h"
59 #include "MagickCore/utility-private.h"
60 #include "MagickCore/xml-tree.h"
61 #include "MagickCore/xml-tree-private.h"
62 \f
63 /*
64   Define declarations.
65 */
66 #define MagicPattern(magic)  (const unsigned char *) (magic), sizeof(magic)-1
67 \f
68 /*
69   Typedef declarations.
70 */
71 typedef struct _MagicMapInfo
72 {
73   const char
74     *name;
75
76   const MagickOffsetType
77     offset;
78
79   const unsigned char
80     *magic;
81
82   const size_t
83     length;
84 } MagicMapInfo;
85
86 struct _MagicInfo
87 {
88   char
89     *path,
90     *name,
91     *target;
92
93   unsigned char
94     *magic;
95
96   size_t
97     length;
98
99   MagickOffsetType
100     offset;
101
102   MagickBooleanType
103     exempt,
104     stealth;
105
106   size_t
107     signature;
108 };
109 \f
110 /*
111   Static declarations.
112 */
113 static const MagicMapInfo
114   MagicMap[] =
115   {
116     { "8BIMWTEXT", 0, MagicPattern("8\000B\000I\000M\000#") },
117     { "8BIMTEXT", 0, MagicPattern("8BIM#") },
118     { "8BIM", 0, MagicPattern("8BIM") },
119     { "BMP", 0, MagicPattern("BA") },
120     { "BMP", 0, MagicPattern("BM") },
121     { "BMP", 0, MagicPattern("CI") },
122     { "BMP", 0, MagicPattern("CP") },
123     { "BMP", 0, MagicPattern("IC") },
124     { "PICT", 0, MagicPattern("PICT") },
125     { "BMP", 0, MagicPattern("PI") },
126     { "CALS", 21, MagicPattern("version: MIL-STD-1840") },
127     { "CALS", 0, MagicPattern("srcdocid:") },
128     { "CALS", 9, MagicPattern("srcdocid:") },
129     { "CALS", 8, MagicPattern("rorient:") },
130     { "CGM", 0, MagicPattern("BEGMF") },
131     { "CIN", 0, MagicPattern("\200\052\137\327") },
132     { "CRW", 0, MagicPattern("II\x1a\x00\x00\x00HEAPCCDR") },
133     { "DCM", 128, MagicPattern("DICM") },
134     { "DCX", 0, MagicPattern("\261\150\336\72") },
135     { "DIB", 0, MagicPattern("\050\000") },
136     { "DDS", 0, MagicPattern("DDS ") },
137     { "DJVU", 0, MagicPattern("AT&TFORM") },
138     { "DOT", 0, MagicPattern("digraph") },
139     { "DPX", 0, MagicPattern("SDPX") },
140     { "DPX", 0, MagicPattern("XPDS") },
141     { "EMF", 40, MagicPattern("\040\105\115\106\000\000\001\000") },
142     { "EPT", 0, MagicPattern("\305\320\323\306") },
143     { "EXR", 0, MagicPattern("\166\057\061\001") },
144     { "FAX", 0, MagicPattern("DFAX") },
145     { "FIG", 0, MagicPattern("#FIG") },
146     { "FITS", 0, MagicPattern("IT0") },
147     { "FITS", 0, MagicPattern("SIMPLE") },
148     { "FLIF", 0, MagicPattern("FLIF") },
149     { "GIF", 0, MagicPattern("GIF8") },
150     { "GPLT", 0, MagicPattern("#!/usr/local/bin/gnuplot") },
151     { "HDF", 1, MagicPattern("HDF") },
152     { "HDR", 0, MagicPattern("#?RADIANCE") },
153     { "HDR", 0, MagicPattern("#?RGBE") },
154     { "HEIC", 8, MagicPattern("heic") },
155     { "HPGL", 0, MagicPattern("IN;") },
156     { "HTML", 1, MagicPattern("HTML") },
157     { "HTML", 1, MagicPattern("html") },
158     { "ILBM", 8, MagicPattern("ILBM") },
159     { "IPTCWTEXT", 0, MagicPattern("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
160     { "IPTCTEXT", 0, MagicPattern("2#0=\042�\042") },
161     { "IPTC", 0, MagicPattern("\034\002") },
162     { "JNG", 0, MagicPattern("\213JNG\r\n\032\n") },
163     { "JPEG", 0, MagicPattern("\377\330\377") },
164     { "J2K", 0, MagicPattern("\xff\x4f\xff\x51") },
165     { "JPC", 0, MagicPattern("\x0d\x0a\x87\x0a") },
166     { "JP2", 0, MagicPattern("\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a") },
167     { "MAT", 0, MagicPattern("MATLAB 5.0 MAT-file,") },
168     { "MIFF", 0, MagicPattern("Id=ImageMagick") },
169     { "MIFF", 0, MagicPattern("id=ImageMagick") },
170     { "MNG", 0, MagicPattern("\212MNG\r\n\032\n") },
171     { "MPC", 0, MagicPattern("id=MagickCache") },
172     { "MPEG", 0, MagicPattern("\000\000\001\263") },
173     { "MRW", 0, MagicPattern("\x00MRM") },
174     { "ORF", 0, MagicPattern("IIRO\x08\x00\x00\x00") },
175     { "PCD", 2048, MagicPattern("PCD_") },
176     { "PCL", 0, MagicPattern("\033E\033") },
177     { "PCX", 0, MagicPattern("\012\002") },
178     { "PCX", 0, MagicPattern("\012\005") },
179     { "PDB", 60, MagicPattern("vIMGView") },
180     { "PDF", 0, MagicPattern("%PDF-") },
181     { "PES", 0, MagicPattern("#PES") },
182     { "PFA", 0, MagicPattern("%!PS-AdobeFont-1.0") },
183     { "PFB", 6, MagicPattern("%!PS-AdobeFont-1.0") },
184     { "PGX", 0, MagicPattern("\050\107\020\115\046") },
185     { "PICT", 522, MagicPattern("\000\021\002\377\014\000") },
186     { "PNG", 0, MagicPattern("\211PNG\r\n\032\n") },
187     { "PBM", 0, MagicPattern("P1") },
188     { "PGM", 0, MagicPattern("P2") },
189     { "PPM", 0, MagicPattern("P3") },
190     { "PBM", 0, MagicPattern("P4") },
191     { "PGM", 0, MagicPattern("P5") },
192     { "PPM", 0, MagicPattern("P6") },
193     { "PAM", 0, MagicPattern("P7") },
194     { "PFM", 0, MagicPattern("PF") },
195     { "PFM", 0, MagicPattern("Pf") },
196     { "PGX", 0, MagicPattern("PG ML") },
197     { "PGX", 0, MagicPattern("PG LM") },
198     { "PS", 0, MagicPattern("%!") },
199     { "PS", 0, MagicPattern("\004%!") },
200     { "PS", 0, MagicPattern("\305\320\323\306") },
201     { "PSB", 0, MagicPattern("8BPB") },
202     { "PSD", 0, MagicPattern("8BPS") },
203     { "PWP", 0, MagicPattern("SFW95") },
204     { "RAF", 0, MagicPattern("FUJIFILMCCD-RAW ") },
205     { "RLE", 0, MagicPattern("\122\314") },
206     { "SCT", 0, MagicPattern("CT") },
207     { "SFW", 0, MagicPattern("SFW94") },
208     { "SGI", 0, MagicPattern("\001\332") },
209     { "SUN", 0, MagicPattern("\131\246\152\225") },
210     { "SVG", 1, MagicPattern("?XML") },
211     { "SVG", 1, MagicPattern("?xml") },
212     { "SVG", 1, MagicPattern("SVG") },
213     { "SVG", 1, MagicPattern("svg") },
214     { "TIFF", 0, MagicPattern("\115\115\000\052") },
215     { "TIFF", 0, MagicPattern("\111\111\052\000") },
216     { "TIFF64", 0, MagicPattern("\115\115\000\053\000\010\000\000") },
217     { "TIFF64", 0, MagicPattern("\111\111\053\000\010\000\000\000") },
218     { "TTF", 0, MagicPattern("\000\001\000\000\000") },
219     { "TXT", 0, MagicPattern("# ImageMagick pixel enumeration:") },
220     { "VICAR", 0, MagicPattern("LBLSIZE") },
221     { "VICAR", 0, MagicPattern("NJPL1I") },
222     { "VIFF", 0, MagicPattern("\253\001") },
223     { "WEBP", 8, MagicPattern("WEBP") },
224     { "WMF", 0, MagicPattern("\327\315\306\232") },
225     { "WMF", 0, MagicPattern("\001\000\011\000") },
226     { "WPG", 0, MagicPattern("\377WPC") },
227     { "XBM", 0, MagicPattern("#define") },
228     { "XCF", 0, MagicPattern("gimp xcf") },
229     { "XEF", 0, MagicPattern("FOVb") },
230     { "XPM", 1, MagicPattern("* XPM *") }
231  };
232
233 static LinkedListInfo
234   *magic_cache = (LinkedListInfo *) NULL,
235   *magic_list = (LinkedListInfo *) NULL;
236
237 static SemaphoreInfo
238   *magic_cache_semaphore = (SemaphoreInfo *) NULL,
239   *magic_list_semaphore = (SemaphoreInfo *) NULL;
240 \f
241 /*
242   Forward declarations.
243 */
244 static MagickBooleanType
245   IsMagicListInstantiated(ExceptionInfo *);
246 \f
247 /*
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 %                                                                             %
250 %                                                                             %
251 %                                                                             %
252 %  A c q u i r e M a g i c L i s t                                            %
253 %                                                                             %
254 %                                                                             %
255 %                                                                             %
256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 %
258 %  AcquireMagicList() caches one or more magic configurations which provides a
259 %  mapping between magic attributes and a magic name.
260 %
261 %  The format of the AcquireMagicList method is:
262 %
263 %      LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
264 %
265 %  A description of each parameter follows:
266 %
267 %    o filename: the font file name.
268 %
269 %    o exception: return any errors or warnings in this structure.
270 %
271 */
272 static int CompareMagickInfoSize(const void *a,const void *b)
273 {
274   MagicInfo
275     *ma,
276     *mb;
277
278   ma=(MagicInfo *) a;
279   mb=(MagicInfo *) b;
280   if (ma->offset != mb->offset)
281     return((int) (ma->offset-mb->offset));
282   return((int) (mb->length-ma->length));
283 }
284
285 static LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
286 {
287   LinkedListInfo
288     *list;
289
290   MagickStatusType
291     status;
292
293   register ssize_t
294     i;
295
296   list=NewLinkedList(0);
297   status=MagickTrue;
298   /*
299     Load built-in magic map.
300   */
301   for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
302   {
303     MagicInfo
304       *magic_info;
305
306     register const MagicMapInfo
307       *p;
308
309     p=MagicMap+i;
310     magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
311     if (magic_info == (MagicInfo *) NULL)
312       {
313         (void) ThrowMagickException(exception,GetMagickModule(),
314           ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
315         continue;
316       }
317     (void) memset(magic_info,0,sizeof(*magic_info));
318     magic_info->path=(char *) "[built-in]";
319     magic_info->name=(char *) p->name;
320     magic_info->offset=p->offset;
321     magic_info->target=(char *) p->magic;
322     magic_info->magic=(unsigned char *) p->magic;
323     magic_info->length=p->length;
324     magic_info->exempt=MagickTrue;
325     magic_info->signature=MagickCoreSignature;
326     status&=InsertValueInSortedLinkedList(list,CompareMagickInfoSize,
327       NULL,magic_info);
328     if (status == MagickFalse)
329       (void) ThrowMagickException(exception,GetMagickModule(),
330         ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
331   }
332   return(list);
333 }
334 \f
335 /*
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %                                                                             %
338 %                                                                             %
339 %                                                                             %
340 %   G e t M a g i c I n f o                                                   %
341 %                                                                             %
342 %                                                                             %
343 %                                                                             %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 %
346 %  GetMagicInfo() searches the magic list for the specified name and if found
347 %  returns attributes for that magic.
348 %
349 %  The format of the GetMagicInfo method is:
350 %
351 %      const MagicInfo *GetMagicInfo(const unsigned char *magic,
352 %        const size_t length,ExceptionInfo *exception)
353 %
354 %  A description of each parameter follows:
355 %
356 %    o magic: A binary string generally representing the first few characters
357 %      of the image file or blob.
358 %
359 %    o length: the length of the binary signature.
360 %
361 %    o exception: return any errors or warnings in this structure.
362 %
363 */
364 static MagickBooleanType IsMagicCacheInstantiated()
365 {
366   if (magic_cache == (LinkedListInfo *) NULL)
367     {
368       if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
369         ActivateSemaphoreInfo(&magic_cache_semaphore);
370       LockSemaphoreInfo(magic_cache_semaphore);
371       if (magic_cache == (LinkedListInfo *) NULL)
372         magic_cache=NewLinkedList(0);
373       UnlockSemaphoreInfo(magic_cache_semaphore);
374     }
375   return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
376 }
377
378 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
379   const size_t length,ExceptionInfo *exception)
380 {
381   register const MagicInfo
382     *p;
383
384   assert(exception != (ExceptionInfo *) NULL);
385   if (IsMagicListInstantiated(exception) == MagickFalse)
386     return((const MagicInfo *) NULL);
387   if (IsMagicCacheInstantiated() == MagickFalse)
388     return((const MagicInfo *) NULL);
389   /*
390     Search for cached entries.
391   */
392   if (magic != (const unsigned char *) NULL)
393     {
394       LockSemaphoreInfo(magic_cache_semaphore);
395       ResetLinkedListIterator(magic_cache);
396       p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
397       while (p != (const MagicInfo *) NULL)
398       {
399         if (((size_t) (p->offset+p->length) <= length) &&
400             (memcmp(magic+p->offset,p->magic,p->length) == 0))
401           break;
402         p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
403       }
404       UnlockSemaphoreInfo(magic_cache_semaphore);
405       if (p != (const MagicInfo *) NULL)
406         return(p);
407     }
408   /*
409     Search for magic tag.
410   */
411   LockSemaphoreInfo(magic_list_semaphore);
412   ResetLinkedListIterator(magic_list);
413   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
414   if (magic == (const unsigned char *) NULL)
415     {
416       UnlockSemaphoreInfo(magic_list_semaphore);
417       return(p);
418     }
419   while (p != (const MagicInfo *) NULL)
420   {
421     assert(p->offset >= 0);
422     if (((size_t) (p->offset+p->length) <= length) &&
423         (memcmp(magic+p->offset,p->magic,p->length) == 0))
424       break;
425     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
426   }
427   UnlockSemaphoreInfo(magic_list_semaphore);
428   if (p != (const MagicInfo *) NULL)
429     {
430       LockSemaphoreInfo(magic_cache_semaphore);
431       InsertValueInSortedLinkedList(magic_cache,CompareMagickInfoSize,
432         NULL,p);
433       UnlockSemaphoreInfo(magic_cache_semaphore);
434     }
435   return(p);
436 }
437
438 /*
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440 %                                                                             %
441 %                                                                             %
442 %                                                                             %
443 %   G e t M a g i c P a t t e r n E x t e n t                                 %
444 %                                                                             %
445 %                                                                             %
446 %                                                                             %
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 %
449 %  GetMagicPatternExtent() returns the the extent of the buffer that is
450 %  required to check all the MagickInfos. It returns zero if the list is empty.
451 %
452 %  The format of the GetMagicPatternExtent method is:
453 %
454 %      size_t GetMagicPatternExtent(ExceptionInfo *exception)
455 %
456 %  A description of each parameter follows:
457 %
458 %    o exception: return any errors or warnings in this structure.
459 %
460 */
461 MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
462 {
463   register const MagicInfo
464     *p;
465
466   size_t
467     magickSize,
468     max;
469
470   static size_t
471     size=0;
472
473   assert(exception != (ExceptionInfo *) NULL);
474   if ((size != 0) || (IsMagicListInstantiated(exception) == MagickFalse))
475     return(size);
476   LockSemaphoreInfo(magic_list_semaphore);
477   ResetLinkedListIterator(magic_list);
478   max=0;
479   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
480   while (p != (const MagicInfo *) NULL)
481   {
482     magickSize=(size_t) (p->offset+p->length);
483     if (magickSize > max)
484       max=magickSize;
485     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
486   }
487   size=max;
488   UnlockSemaphoreInfo(magic_list_semaphore);
489   return(size);
490 }
491 \f
492 /*
493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494 %                                                                             %
495 %                                                                             %
496 %                                                                             %
497 %   G e t M a g i c I n f o L i s t                                           %
498 %                                                                             %
499 %                                                                             %
500 %                                                                             %
501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
502 %
503 %  GetMagicInfoList() returns any image aliases that match the specified
504 %  pattern.
505 %
506 %  The magic of the GetMagicInfoList function is:
507 %
508 %      const MagicInfo **GetMagicInfoList(const char *pattern,
509 %        size_t *number_aliases,ExceptionInfo *exception)
510 %
511 %  A description of each parameter follows:
512 %
513 %    o pattern: Specifies a pointer to a text string containing a pattern.
514 %
515 %    o number_aliases:  This integer returns the number of aliases in the list.
516 %
517 %    o exception: return any errors or warnings in this structure.
518 %
519 */
520
521 #if defined(__cplusplus) || defined(c_plusplus)
522 extern "C" {
523 #endif
524
525 static int MagicInfoCompare(const void *x,const void *y)
526 {
527   const MagicInfo
528     **p,
529     **q;
530
531   p=(const MagicInfo **) x,
532   q=(const MagicInfo **) y;
533   if (LocaleCompare((*p)->path,(*q)->path) == 0)
534     return(LocaleCompare((*p)->name,(*q)->name));
535   return(LocaleCompare((*p)->path,(*q)->path));
536 }
537
538 #if defined(__cplusplus) || defined(c_plusplus)
539 }
540 #endif
541
542 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
543   size_t *number_aliases,ExceptionInfo *exception)
544 {
545   const MagicInfo
546     **aliases;
547
548   register const MagicInfo
549     *p;
550
551   register ssize_t
552     i;
553
554   /*
555     Allocate magic list.
556   */
557   assert(pattern != (char *) NULL);
558   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
559   assert(number_aliases != (size_t *) NULL);
560   *number_aliases=0;
561   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
562   if (p == (const MagicInfo *) NULL)
563     return((const MagicInfo **) NULL);
564   aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
565     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
566   if (aliases == (const MagicInfo **) NULL)
567     return((const MagicInfo **) NULL);
568   /*
569     Generate magic list.
570   */
571   LockSemaphoreInfo(magic_list_semaphore);
572   ResetLinkedListIterator(magic_list);
573   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
574   for (i=0; p != (const MagicInfo *) NULL; )
575   {
576     if ((p->stealth == MagickFalse) &&
577         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
578       aliases[i++]=p;
579     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
580   }
581   UnlockSemaphoreInfo(magic_list_semaphore);
582   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
583   aliases[i]=(MagicInfo *) NULL;
584   *number_aliases=(size_t) i;
585   return(aliases);
586 }
587 \f
588 /*
589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590 %                                                                             %
591 %                                                                             %
592 %                                                                             %
593 %   G e t M a g i c L i s t                                                   %
594 %                                                                             %
595 %                                                                             %
596 %                                                                             %
597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598 %
599 %  GetMagicList() returns any image format aliases that match the specified
600 %  pattern.
601 %
602 %  The format of the GetMagicList function is:
603 %
604 %      char **GetMagicList(const char *pattern,size_t *number_aliases,
605 %        ExceptionInfo *exception)
606 %
607 %  A description of each parameter follows:
608 %
609 %    o pattern: Specifies a pointer to a text string containing a pattern.
610 %
611 %    o number_aliases:  This integer returns the number of image format aliases
612 %      in the list.
613 %
614 %    o exception: return any errors or warnings in this structure.
615 %
616 */
617
618 #if defined(__cplusplus) || defined(c_plusplus)
619 extern "C" {
620 #endif
621
622 static int MagicCompare(const void *x,const void *y)
623 {
624   register const char
625     *p,
626     *q;
627
628   p=(const char *) x;
629   q=(const char *) y;
630   return(LocaleCompare(p,q));
631 }
632
633 #if defined(__cplusplus) || defined(c_plusplus)
634 }
635 #endif
636
637 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
638   ExceptionInfo *exception)
639 {
640   char
641     **aliases;
642
643   register const MagicInfo
644     *p;
645
646   register ssize_t
647     i;
648
649   /*
650     Allocate configure list.
651   */
652   assert(pattern != (char *) NULL);
653   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
654   assert(number_aliases != (size_t *) NULL);
655   *number_aliases=0;
656   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
657   if (p == (const MagicInfo *) NULL)
658     return((char **) NULL);
659   aliases=(char **) AcquireQuantumMemory((size_t)
660     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
661   if (aliases == (char **) NULL)
662     return((char **) NULL);
663   LockSemaphoreInfo(magic_list_semaphore);
664   ResetLinkedListIterator(magic_list);
665   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
666   for (i=0; p != (const MagicInfo *) NULL; )
667   {
668     if ((p->stealth == MagickFalse) &&
669         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
670       aliases[i++]=ConstantString(p->name);
671     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
672   }
673   UnlockSemaphoreInfo(magic_list_semaphore);
674   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
675   aliases[i]=(char *) NULL;
676   *number_aliases=(size_t) i;
677   return(aliases);
678 }
679 \f
680 /*
681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682 %                                                                             %
683 %                                                                             %
684 %                                                                             %
685 %   G e t M a g i c N a m e                                                   %
686 %                                                                             %
687 %                                                                             %
688 %                                                                             %
689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 %
691 %  GetMagicName() returns the name associated with the magic.
692 %
693 %  The format of the GetMagicName method is:
694 %
695 %      const char *GetMagicName(const MagicInfo *magic_info)
696 %
697 %  A description of each parameter follows:
698 %
699 %    o magic_info:  The magic info.
700 %
701 */
702 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
703 {
704   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
705   assert(magic_info != (MagicInfo *) NULL);
706   assert(magic_info->signature == MagickCoreSignature);
707   return(magic_info->name);
708 }
709 \f
710 /*
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712 %                                                                             %
713 %                                                                             %
714 %                                                                             %
715 +   I s M a g i c L i s t I n s t a n t i a t e d                             %
716 %                                                                             %
717 %                                                                             %
718 %                                                                             %
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720 %
721 %  IsMagicListInstantiated() determines if the magic list is instantiated.
722 %  If not, it instantiates the list and returns it.
723 %
724 %  The format of the IsMagicListInstantiated method is:
725 %
726 %      MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
727 %
728 %  A description of each parameter follows.
729 %
730 %    o exception: return any errors or warnings in this structure.
731 %
732 */
733 static MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
734 {
735   if (magic_list == (LinkedListInfo *) NULL)
736     {
737       if (magic_list_semaphore == (SemaphoreInfo *) NULL)
738         ActivateSemaphoreInfo(&magic_list_semaphore);
739       LockSemaphoreInfo(magic_list_semaphore);
740       if (magic_list == (LinkedListInfo *) NULL)
741         magic_list=AcquireMagicList(exception);
742       UnlockSemaphoreInfo(magic_list_semaphore);
743     }
744   return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
745 }
746 \f
747 /*
748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 %                                                                             %
750 %                                                                             %
751 %                                                                             %
752 %  L i s t M a g i c I n f o                                                  %
753 %                                                                             %
754 %                                                                             %
755 %                                                                             %
756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
757 %
758 %  ListMagicInfo() lists the magic info to a file.
759 %
760 %  The format of the ListMagicInfo method is:
761 %
762 %      MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
763 %
764 %  A description of each parameter follows.
765 %
766 %    o file:  An pointer to a FILE.
767 %
768 %    o exception: return any errors or warnings in this structure.
769 %
770 */
771 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
772   ExceptionInfo *exception)
773 {
774   const char
775     *path;
776
777   const MagicInfo
778     **magic_info;
779
780   register ssize_t
781     i;
782
783   size_t
784     number_aliases;
785
786   ssize_t
787     j;
788
789   if (file == (const FILE *) NULL)
790     file=stdout;
791   magic_info=GetMagicInfoList("*",&number_aliases,exception);
792   if (magic_info == (const MagicInfo **) NULL)
793     return(MagickFalse);
794   path=(const char *) NULL;
795   for (i=0; i < (ssize_t) number_aliases; i++)
796   {
797     if (magic_info[i]->stealth != MagickFalse)
798       continue;
799     if ((path == (const char *) NULL) ||
800         (LocaleCompare(path,magic_info[i]->path) != 0))
801       {
802         if (magic_info[i]->path != (char *) NULL)
803           (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
804         (void) FormatLocaleFile(file,"Name      Offset Target\n");
805         (void) FormatLocaleFile(file,
806           "-------------------------------------------------"
807           "------------------------------\n");
808       }
809     path=magic_info[i]->path;
810     (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
811     for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
812       (void) FormatLocaleFile(file," ");
813     (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
814     if (magic_info[i]->target != (char *) NULL)
815       {
816         for (j=0; magic_info[i]->target[j] != '\0'; j++)
817           if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
818             (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
819           else
820             (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
821               ((unsigned char) magic_info[i]->target[j]));
822       }
823     (void) FormatLocaleFile(file,"\n");
824   }
825   (void) fflush(file);
826   magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
827   return(MagickTrue);
828 }
829 \f
830 /*
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 %                                                                             %
833 %                                                                             %
834 %                                                                             %
835 +   M a g i c C o m p o n e n t G e n e s i s                                 %
836 %                                                                             %
837 %                                                                             %
838 %                                                                             %
839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
840 %
841 %  MagicComponentGenesis() instantiates the magic component.
842 %
843 %  The format of the MagicComponentGenesis method is:
844 %
845 %      MagickBooleanType MagicComponentGenesis(void)
846 %
847 */
848 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
849 {
850   if (magic_list_semaphore == (SemaphoreInfo *) NULL)
851     magic_list_semaphore=AcquireSemaphoreInfo();
852   return(MagickTrue);
853 }
854 \f
855 /*
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 %                                                                             %
858 %                                                                             %
859 %                                                                             %
860 +   M a g i c C o m p o n e n t T e r m i n u s                               %
861 %                                                                             %
862 %                                                                             %
863 %                                                                             %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 %
866 %  MagicComponentTerminus() destroys the magic component.
867 %
868 %  The format of the MagicComponentTerminus method is:
869 %
870 %      MagicComponentTerminus(void)
871 %
872 */
873
874 static void *DestroyMagicElement(void *magic_info)
875 {
876   register MagicInfo
877     *p;
878
879   p=(MagicInfo *) magic_info;
880   if (p->exempt == MagickFalse)
881     {
882       if (p->path != (char *) NULL)
883         p->path=DestroyString(p->path);
884       if (p->name != (char *) NULL)
885         p->name=DestroyString(p->name);
886       if (p->target != (char *) NULL)
887         p->target=DestroyString(p->target);
888       if (p->magic != (unsigned char *) NULL)
889         p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
890     }
891   p=(MagicInfo *) RelinquishMagickMemory(p);
892   return((void *) NULL);
893 }
894
895 MagickPrivate void MagicComponentTerminus(void)
896 {
897   if (magic_list_semaphore == (SemaphoreInfo *) NULL)
898     ActivateSemaphoreInfo(&magic_list_semaphore);
899   LockSemaphoreInfo(magic_list_semaphore);
900   if (magic_list != (LinkedListInfo *) NULL)
901     magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
902   UnlockSemaphoreInfo(magic_list_semaphore);
903   RelinquishSemaphoreInfo(&magic_list_semaphore);
904 }