• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2021 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 
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 "coders/coders.h"
61 
62 /*
63   Define declarations.
64 */
65 #define AddMagickCoder(coder) Magick ## coder ## Headers
66 
67 /*
68   Typedef declarations.
69 */
70 typedef struct _MagicMapInfo
71 {
72   const char
73     name[10];
74 
75   const MagickOffsetType
76     offset;
77 
78   const unsigned char
79     *const magic;
80 
81   const size_t
82     length;
83 } MagicMapInfo;
84 
85 struct _MagicInfo
86 {
87   char
88     *path,
89     *name,
90     *target;
91 
92   unsigned char
93     *magic;
94 
95   size_t
96     length;
97 
98   MagickOffsetType
99     offset;
100 
101   MagickBooleanType
102     exempt,
103     stealth;
104 
105   size_t
106     signature;
107 };
108 
109 /*
110   Static declarations.
111 */
112 static const MagicMapInfo
113   MagicMap[] =
114   {
115     #include "coders/coders-list.h"
116     MagickCoderHeader("CGM", 0, "BEGMF")
117     MagickCoderHeader("FIG", 0, "#FIG")
118     MagickCoderHeader("HPGL", 0, "IN;")
119     MagickCoderHeader("ILBM", 8, "ILBM")
120   };
121 
122 static LinkedListInfo
123   *magic_cache = (LinkedListInfo *) NULL,
124   *magic_list = (LinkedListInfo *) NULL;
125 
126 static SemaphoreInfo
127   *magic_cache_semaphore = (SemaphoreInfo *) NULL,
128   *magic_list_semaphore = (SemaphoreInfo *) NULL;
129 
130 /*
131   Forward declarations.
132 */
133 static MagickBooleanType
134   IsMagicListInstantiated(ExceptionInfo *);
135 
136 /*
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 %                                                                             %
139 %                                                                             %
140 %                                                                             %
141 %  A c q u i r e M a g i c L i s t                                            %
142 %                                                                             %
143 %                                                                             %
144 %                                                                             %
145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 %
147 %  AcquireMagicList() caches one or more magic configurations which provides a
148 %  mapping between magic attributes and a magic name.
149 %
150 %  The format of the AcquireMagicList method is:
151 %
152 %      LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
153 %
154 %  A description of each parameter follows:
155 %
156 %    o filename: the font file name.
157 %
158 %    o exception: return any errors or warnings in this structure.
159 %
160 */
161 
CompareMagickInfoExtent(const void * a,const void * b)162 static int CompareMagickInfoExtent(const void *a,const void *b)
163 {
164   MagicInfo
165     *ma,
166     *mb;
167 
168   MagickOffsetType
169     delta;
170 
171   ma=(MagicInfo *) a;
172   mb=(MagicInfo *) b;
173   delta=(MagickOffsetType) mb->length-(MagickOffsetType) ma->length;
174   if (ma->offset != mb->offset)
175     {
176       /*
177         Offset is near the start? Let's search a bit further in the stream.
178       */
179       delta=ma->offset-mb->offset;
180       if ((ma->offset > mb->offset ? ma->offset : mb->offset) <= 10)
181         delta=mb->offset-ma->offset;
182     }
183   return(delta > INT_MAX ? 0 : (int) delta);
184 }
185 
AcquireMagicList(ExceptionInfo * exception)186 static LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
187 {
188   LinkedListInfo
189     *list;
190 
191   MagickStatusType
192     status;
193 
194   ssize_t
195     i;
196 
197   list=NewLinkedList(0);
198   status=MagickTrue;
199   /*
200     Load built-in magic map.
201   */
202   for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
203   {
204     MagicInfo
205       *magic_info;
206 
207     const MagicMapInfo
208       *p;
209 
210     p=MagicMap+i;
211     magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
212     if (magic_info == (MagicInfo *) NULL)
213       {
214         (void) ThrowMagickException(exception,GetMagickModule(),
215           ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
216         continue;
217       }
218     (void) memset(magic_info,0,sizeof(*magic_info));
219     magic_info->path=(char *) "[built-in]";
220     magic_info->name=(char *) p->name;
221     magic_info->offset=p->offset;
222     magic_info->target=(char *) p->magic;
223     magic_info->magic=(unsigned char *) p->magic;
224     magic_info->length=p->length;
225     magic_info->exempt=MagickTrue;
226     magic_info->signature=MagickCoreSignature;
227     status&=InsertValueInSortedLinkedList(list,CompareMagickInfoExtent,
228       NULL,magic_info);
229     if (status == MagickFalse)
230       (void) ThrowMagickException(exception,GetMagickModule(),
231         ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
232   }
233   return(list);
234 }
235 
236 /*
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 %                                                                             %
239 %                                                                             %
240 %                                                                             %
241 %   G e t M a g i c I n f o                                                   %
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %
247 %  GetMagicInfo() searches the magic list for the specified name and if found
248 %  returns attributes for that magic.
249 %
250 %  The format of the GetMagicInfo method is:
251 %
252 %      const MagicInfo *GetMagicInfo(const unsigned char *magic,
253 %        const size_t length,ExceptionInfo *exception)
254 %
255 %  A description of each parameter follows:
256 %
257 %    o magic: A binary string generally representing the first few characters
258 %      of the image file or blob.
259 %
260 %    o length: the length of the binary signature.
261 %
262 %    o exception: return any errors or warnings in this structure.
263 %
264 */
IsMagicCacheInstantiated()265 static MagickBooleanType IsMagicCacheInstantiated()
266 {
267   if (magic_cache == (LinkedListInfo *) NULL)
268     {
269       if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
270         ActivateSemaphoreInfo(&magic_cache_semaphore);
271       LockSemaphoreInfo(magic_cache_semaphore);
272       if (magic_cache == (LinkedListInfo *) NULL)
273         magic_cache=NewLinkedList(0);
274       UnlockSemaphoreInfo(magic_cache_semaphore);
275     }
276   return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
277 }
278 
GetMagicInfo(const unsigned char * magic,const size_t length,ExceptionInfo * exception)279 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
280   const size_t length,ExceptionInfo *exception)
281 {
282   const MagicInfo
283     *p;
284 
285   MagickOffsetType
286     offset;
287 
288   assert(exception != (ExceptionInfo *) NULL);
289   if (IsMagicListInstantiated(exception) == MagickFalse)
290     return((const MagicInfo *) NULL);
291   if (IsMagicCacheInstantiated() == MagickFalse)
292     return((const MagicInfo *) NULL);
293   /*
294     Search for cached entries.
295   */
296   if (magic != (const unsigned char *) NULL)
297     {
298       LockSemaphoreInfo(magic_cache_semaphore);
299       ResetLinkedListIterator(magic_cache);
300       p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
301       while (p != (const MagicInfo *) NULL)
302       {
303         offset=p->offset+(MagickOffsetType) p->length;
304         if ((offset <= (MagickOffsetType) length) &&
305             (memcmp(magic+p->offset,p->magic,p->length) == 0))
306           break;
307         p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
308       }
309       UnlockSemaphoreInfo(magic_cache_semaphore);
310       if (p != (const MagicInfo *) NULL)
311         return(p);
312     }
313   /*
314     Search for magic tag.
315   */
316   LockSemaphoreInfo(magic_list_semaphore);
317   ResetLinkedListIterator(magic_list);
318   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
319   if (magic == (const unsigned char *) NULL)
320     {
321       UnlockSemaphoreInfo(magic_list_semaphore);
322       return(p);
323     }
324   while (p != (const MagicInfo *) NULL)
325   {
326     assert(p->offset >= 0);
327     offset=p->offset+(MagickOffsetType) p->length;
328     if ((offset <= (MagickOffsetType) length) &&
329         (memcmp(magic+p->offset,p->magic,p->length) == 0))
330       break;
331     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
332   }
333   UnlockSemaphoreInfo(magic_list_semaphore);
334   if (p != (const MagicInfo *) NULL)
335     {
336       LockSemaphoreInfo(magic_cache_semaphore);
337       (void) InsertValueInSortedLinkedList(magic_cache,CompareMagickInfoExtent,
338         NULL,p);
339       UnlockSemaphoreInfo(magic_cache_semaphore);
340     }
341   return(p);
342 }
343 
344 /*
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 %                                                                             %
347 %                                                                             %
348 %                                                                             %
349 %   G e t M a g i c P a t t e r n E x t e n t                                 %
350 %                                                                             %
351 %                                                                             %
352 %                                                                             %
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 %
355 %  GetMagicPatternExtent() returns the extent of the buffer that is
356 %  required to check all the MagickInfos. It returns zero if the list is empty.
357 %
358 %  The format of the GetMagicPatternExtent method is:
359 %
360 %      size_t GetMagicPatternExtent(ExceptionInfo *exception)
361 %
362 %  A description of each parameter follows:
363 %
364 %    o exception: return any errors or warnings in this structure.
365 %
366 */
GetMagicPatternExtent(ExceptionInfo * exception)367 MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
368 {
369   const MagicInfo
370     *p;
371 
372   MagickOffsetType
373     max_offset,
374     offset;
375 
376   static size_t
377     extent = 0;
378 
379   assert(exception != (ExceptionInfo *) NULL);
380   if ((extent != 0) || (IsMagicListInstantiated(exception) == MagickFalse))
381     return(extent);
382   LockSemaphoreInfo(magic_list_semaphore);
383   ResetLinkedListIterator(magic_list);
384   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
385   for (max_offset=0; p != (const MagicInfo *) NULL; )
386   {
387     offset=p->offset+(MagickOffsetType) p->length;
388     if (offset > max_offset)
389       max_offset=offset;
390     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
391   }
392   if (max_offset > (MagickOffsetType) MAGICK_SSIZE_MAX)
393     return(0);
394   extent=(size_t) max_offset;
395   UnlockSemaphoreInfo(magic_list_semaphore);
396   return(extent);
397 }
398 
399 /*
400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401 %                                                                             %
402 %                                                                             %
403 %                                                                             %
404 %   G e t M a g i c I n f o L i s t                                           %
405 %                                                                             %
406 %                                                                             %
407 %                                                                             %
408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409 %
410 %  GetMagicInfoList() returns any image aliases that match the specified
411 %  pattern.
412 %
413 %  The magic of the GetMagicInfoList function is:
414 %
415 %      const MagicInfo **GetMagicInfoList(const char *pattern,
416 %        size_t *number_aliases,ExceptionInfo *exception)
417 %
418 %  A description of each parameter follows:
419 %
420 %    o pattern: Specifies a pointer to a text string containing a pattern.
421 %
422 %    o number_aliases:  This integer returns the number of aliases in the list.
423 %
424 %    o exception: return any errors or warnings in this structure.
425 %
426 */
427 
428 #if defined(__cplusplus) || defined(c_plusplus)
429 extern "C" {
430 #endif
431 
MagicInfoCompare(const void * x,const void * y)432 static int MagicInfoCompare(const void *x,const void *y)
433 {
434   const MagicInfo
435     **p,
436     **q;
437 
438   p=(const MagicInfo **) x,
439   q=(const MagicInfo **) y;
440   if (LocaleCompare((*p)->path,(*q)->path) == 0)
441     return(LocaleCompare((*p)->name,(*q)->name));
442   return(LocaleCompare((*p)->path,(*q)->path));
443 }
444 
445 #if defined(__cplusplus) || defined(c_plusplus)
446 }
447 #endif
448 
GetMagicInfoList(const char * pattern,size_t * number_aliases,ExceptionInfo * exception)449 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
450   size_t *number_aliases,ExceptionInfo *exception)
451 {
452   const MagicInfo
453     **aliases;
454 
455   const MagicInfo
456     *p;
457 
458   ssize_t
459     i;
460 
461   /*
462     Allocate magic list.
463   */
464   assert(pattern != (char *) NULL);
465   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
466   assert(number_aliases != (size_t *) NULL);
467   *number_aliases=0;
468   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
469   if (p == (const MagicInfo *) NULL)
470     return((const MagicInfo **) NULL);
471   aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
472     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
473   if (aliases == (const MagicInfo **) NULL)
474     return((const MagicInfo **) NULL);
475   /*
476     Generate magic list.
477   */
478   LockSemaphoreInfo(magic_list_semaphore);
479   ResetLinkedListIterator(magic_list);
480   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
481   for (i=0; p != (const MagicInfo *) NULL; )
482   {
483     if ((p->stealth == MagickFalse) &&
484         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
485       aliases[i++]=p;
486     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
487   }
488   UnlockSemaphoreInfo(magic_list_semaphore);
489   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
490   aliases[i]=(MagicInfo *) NULL;
491   *number_aliases=(size_t) i;
492   return(aliases);
493 }
494 
495 /*
496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497 %                                                                             %
498 %                                                                             %
499 %                                                                             %
500 %   G e t M a g i c L i s t                                                   %
501 %                                                                             %
502 %                                                                             %
503 %                                                                             %
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 %
506 %  GetMagicList() returns any image format aliases that match the specified
507 %  pattern.
508 %
509 %  The format of the GetMagicList function is:
510 %
511 %      char **GetMagicList(const char *pattern,size_t *number_aliases,
512 %        ExceptionInfo *exception)
513 %
514 %  A description of each parameter follows:
515 %
516 %    o pattern: Specifies a pointer to a text string containing a pattern.
517 %
518 %    o number_aliases:  This integer returns the number of image format aliases
519 %      in the list.
520 %
521 %    o exception: return any errors or warnings in this structure.
522 %
523 */
524 
525 #if defined(__cplusplus) || defined(c_plusplus)
526 extern "C" {
527 #endif
528 
MagicCompare(const void * x,const void * y)529 static int MagicCompare(const void *x,const void *y)
530 {
531   const char
532     *p,
533     *q;
534 
535   p=(const char *) x;
536   q=(const char *) y;
537   return(LocaleCompare(p,q));
538 }
539 
540 #if defined(__cplusplus) || defined(c_plusplus)
541 }
542 #endif
543 
GetMagicList(const char * pattern,size_t * number_aliases,ExceptionInfo * exception)544 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
545   ExceptionInfo *exception)
546 {
547   char
548     **aliases;
549 
550   const MagicInfo
551     *p;
552 
553   ssize_t
554     i;
555 
556   /*
557     Allocate configure list.
558   */
559   assert(pattern != (char *) NULL);
560   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
561   assert(number_aliases != (size_t *) NULL);
562   *number_aliases=0;
563   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
564   if (p == (const MagicInfo *) NULL)
565     return((char **) NULL);
566   aliases=(char **) AcquireQuantumMemory((size_t)
567     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
568   if (aliases == (char **) NULL)
569     return((char **) NULL);
570   LockSemaphoreInfo(magic_list_semaphore);
571   ResetLinkedListIterator(magic_list);
572   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
573   for (i=0; p != (const MagicInfo *) NULL; )
574   {
575     if ((p->stealth == MagickFalse) &&
576         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
577       aliases[i++]=ConstantString(p->name);
578     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
579   }
580   UnlockSemaphoreInfo(magic_list_semaphore);
581   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
582   aliases[i]=(char *) NULL;
583   *number_aliases=(size_t) i;
584   return(aliases);
585 }
586 
587 /*
588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 %                                                                             %
590 %                                                                             %
591 %                                                                             %
592 %   G e t M a g i c N a m e                                                   %
593 %                                                                             %
594 %                                                                             %
595 %                                                                             %
596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597 %
598 %  GetMagicName() returns the name associated with the magic.
599 %
600 %  The format of the GetMagicName method is:
601 %
602 %      const char *GetMagicName(const MagicInfo *magic_info)
603 %
604 %  A description of each parameter follows:
605 %
606 %    o magic_info:  The magic info.
607 %
608 */
GetMagicName(const MagicInfo * magic_info)609 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
610 {
611   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
612   assert(magic_info != (MagicInfo *) NULL);
613   assert(magic_info->signature == MagickCoreSignature);
614   return(magic_info->name);
615 }
616 
617 /*
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %                                                                             %
620 %                                                                             %
621 %                                                                             %
622 +   I s M a g i c L i s t I n s t a n t i a t e d                             %
623 %                                                                             %
624 %                                                                             %
625 %                                                                             %
626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 %
628 %  IsMagicListInstantiated() determines if the magic list is instantiated.
629 %  If not, it instantiates the list and returns it.
630 %
631 %  The format of the IsMagicListInstantiated method is:
632 %
633 %      MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
634 %
635 %  A description of each parameter follows.
636 %
637 %    o exception: return any errors or warnings in this structure.
638 %
639 */
IsMagicListInstantiated(ExceptionInfo * exception)640 static MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
641 {
642   if (magic_list == (LinkedListInfo *) NULL)
643     {
644       if (magic_list_semaphore == (SemaphoreInfo *) NULL)
645         ActivateSemaphoreInfo(&magic_list_semaphore);
646       LockSemaphoreInfo(magic_list_semaphore);
647       if (magic_list == (LinkedListInfo *) NULL)
648         magic_list=AcquireMagicList(exception);
649       UnlockSemaphoreInfo(magic_list_semaphore);
650     }
651   return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
652 }
653 
654 /*
655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656 %                                                                             %
657 %                                                                             %
658 %                                                                             %
659 %  L i s t M a g i c I n f o                                                  %
660 %                                                                             %
661 %                                                                             %
662 %                                                                             %
663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664 %
665 %  ListMagicInfo() lists the magic info to a file.
666 %
667 %  The format of the ListMagicInfo method is:
668 %
669 %      MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
670 %
671 %  A description of each parameter follows.
672 %
673 %    o file:  An pointer to a FILE.
674 %
675 %    o exception: return any errors or warnings in this structure.
676 %
677 */
ListMagicInfo(FILE * file,ExceptionInfo * exception)678 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
679   ExceptionInfo *exception)
680 {
681   const char
682     *path;
683 
684   const MagicInfo
685     **magic_info;
686 
687   ssize_t
688     i;
689 
690   size_t
691     number_aliases;
692 
693   ssize_t
694     j;
695 
696   if (file == (const FILE *) NULL)
697     file=stdout;
698   magic_info=GetMagicInfoList("*",&number_aliases,exception);
699   if (magic_info == (const MagicInfo **) NULL)
700     return(MagickFalse);
701   path=(const char *) NULL;
702   for (i=0; i < (ssize_t) number_aliases; i++)
703   {
704     if (magic_info[i]->stealth != MagickFalse)
705       continue;
706     if ((path == (const char *) NULL) ||
707         (LocaleCompare(path,magic_info[i]->path) != 0))
708       {
709         if (magic_info[i]->path != (char *) NULL)
710           (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
711         (void) FormatLocaleFile(file,"Name      Offset Target\n");
712         (void) FormatLocaleFile(file,
713           "-------------------------------------------------"
714           "------------------------------\n");
715       }
716     path=magic_info[i]->path;
717     (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
718     for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
719       (void) FormatLocaleFile(file," ");
720     (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
721     if (magic_info[i]->target != (char *) NULL)
722       {
723         for (j=0; magic_info[i]->target[j] != '\0'; j++)
724           if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
725             (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
726           else
727             (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
728               ((unsigned char) magic_info[i]->target[j]));
729       }
730     (void) FormatLocaleFile(file,"\n");
731   }
732   (void) fflush(file);
733   magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
734   return(MagickTrue);
735 }
736 
737 /*
738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
739 %                                                                             %
740 %                                                                             %
741 %                                                                             %
742 +   M a g i c C o m p o n e n t G e n e s i s                                 %
743 %                                                                             %
744 %                                                                             %
745 %                                                                             %
746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
747 %
748 %  MagicComponentGenesis() instantiates the magic component.
749 %
750 %  The format of the MagicComponentGenesis method is:
751 %
752 %      MagickBooleanType MagicComponentGenesis(void)
753 %
754 */
MagicComponentGenesis(void)755 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
756 {
757   if (magic_list_semaphore == (SemaphoreInfo *) NULL)
758     magic_list_semaphore=AcquireSemaphoreInfo();
759   return(MagickTrue);
760 }
761 
762 /*
763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 %                                                                             %
765 %                                                                             %
766 %                                                                             %
767 +   M a g i c C o m p o n e n t T e r m i n u s                               %
768 %                                                                             %
769 %                                                                             %
770 %                                                                             %
771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
772 %
773 %  MagicComponentTerminus() destroys the magic component.
774 %
775 %  The format of the MagicComponentTerminus method is:
776 %
777 %      MagicComponentTerminus(void)
778 %
779 */
780 
DestroyMagicElement(void * magic_info)781 static void *DestroyMagicElement(void *magic_info)
782 {
783   MagicInfo
784     *p;
785 
786   p=(MagicInfo *) magic_info;
787   if (p->exempt == MagickFalse)
788     {
789       if (p->path != (char *) NULL)
790         p->path=DestroyString(p->path);
791       if (p->name != (char *) NULL)
792         p->name=DestroyString(p->name);
793       if (p->target != (char *) NULL)
794         p->target=DestroyString(p->target);
795       if (p->magic != (unsigned char *) NULL)
796         p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
797     }
798   p=(MagicInfo *) RelinquishMagickMemory(p);
799   return((void *) NULL);
800 }
801 
MagicComponentTerminus(void)802 MagickPrivate void MagicComponentTerminus(void)
803 {
804   if (magic_list_semaphore == (SemaphoreInfo *) NULL)
805     ActivateSemaphoreInfo(&magic_list_semaphore);
806   LockSemaphoreInfo(magic_list_semaphore);
807   if (magic_list != (LinkedListInfo *) NULL)
808     magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
809   UnlockSemaphoreInfo(magic_list_semaphore);
810   RelinquishSemaphoreInfo(&magic_list_semaphore);
811   if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
812     ActivateSemaphoreInfo(&magic_cache_semaphore);
813   LockSemaphoreInfo(magic_cache_semaphore);
814   if (magic_cache != (LinkedListInfo *) NULL)
815     magic_cache=DestroyLinkedList(magic_cache,(void *(*)(void *)) NULL);
816   UnlockSemaphoreInfo(magic_cache_semaphore);
817   RelinquishSemaphoreInfo(&magic_cache_semaphore);
818 }
819