MagickCore  7.1.0
Convert, Edit, Or Compose Bitmap Images
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 @ 2000 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 
84  const MagickBooleanType
85  skip_spaces;
86 } MagicMapInfo;
87 
88 struct _MagicInfo
89 {
90  char
91  *name;
92 
93  unsigned char
94  *magic;
95 
96  size_t
97  length;
98 
99  MagickOffsetType
100  offset;
101 
102  MagickBooleanType
103  skip_spaces;
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 
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 
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->name=(char *) p->name;
220  magic_info->offset=p->offset;
221  magic_info->magic=(unsigned char *) p->magic;
222  magic_info->length=p->length;
223  magic_info->skip_spaces=p->skip_spaces;
224  magic_info->signature=MagickCoreSignature;
225  status&=InsertValueInSortedLinkedList(list,CompareMagickInfoExtent,
226  NULL,magic_info);
227  if (status == MagickFalse)
228  (void) ThrowMagickException(exception,GetMagickModule(),
229  ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
230  }
231  return(list);
232 }
233 ␌
234 /*
235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236 % %
237 % %
238 % %
239 % G e t M a g i c I n f o %
240 % %
241 % %
242 % %
243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 %
245 % GetMagicInfo() searches the magic list for the specified name and if found
246 % returns attributes for that magic.
247 %
248 % The format of the GetMagicInfo method is:
249 %
250 % const MagicInfo *GetMagicInfo(const unsigned char *magic,
251 % const size_t length,ExceptionInfo *exception)
252 %
253 % A description of each parameter follows:
254 %
255 % o magic: A binary string generally representing the first few characters
256 % of the image file or blob.
257 %
258 % o length: the length of the binary signature.
259 %
260 % o exception: return any errors or warnings in this structure.
261 %
262 */
263 
264 static inline MagickBooleanType CompareMagic(const unsigned char *magic,
265  const size_t length,const MagicInfo *magic_info)
266 {
267  const unsigned char
268  *q;
269 
270  MagickOffsetType
271  remaining;
272 
273  assert(magic_info->offset >= 0);
274  q=magic+magic_info->offset;
275  remaining=(MagickOffsetType) length-magic_info->offset;
276  if (magic_info->skip_spaces != MagickFalse)
277  while ((remaining > 0) && (isspace(*q) != 0))
278  {
279  q++;
280  remaining--;
281  }
282  if ((remaining >= (MagickOffsetType) magic_info->length) &&
283  (memcmp(q,magic_info->magic,magic_info->length) == 0))
284  return(MagickTrue);
285  return(MagickFalse);
286 }
287 
288 static MagickBooleanType IsMagicCacheInstantiated()
289 {
290  if (magic_cache == (LinkedListInfo *) NULL)
291  {
292  if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
293  ActivateSemaphoreInfo(&magic_cache_semaphore);
294  LockSemaphoreInfo(magic_cache_semaphore);
295  if (magic_cache == (LinkedListInfo *) NULL)
296  magic_cache=NewLinkedList(0);
297  UnlockSemaphoreInfo(magic_cache_semaphore);
298  }
299  return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
300 }
301 
302 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
303  const size_t length,ExceptionInfo *exception)
304 {
305  const MagicInfo
306  *p;
307 
308  assert(exception != (ExceptionInfo *) NULL);
309  if (IsMagicListInstantiated(exception) == MagickFalse)
310  return((const MagicInfo *) NULL);
311  if (IsMagicCacheInstantiated() == MagickFalse)
312  return((const MagicInfo *) NULL);
313  /*
314  Search for cached entries.
315  */
316  if (magic != (const unsigned char *) NULL)
317  {
318  LockSemaphoreInfo(magic_cache_semaphore);
319  ResetLinkedListIterator(magic_cache);
320  p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
321  while (p != (const MagicInfo *) NULL)
322  {
323  if (CompareMagic(magic,length,p) != MagickFalse)
324  break;
325  p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
326  }
327  UnlockSemaphoreInfo(magic_cache_semaphore);
328  if (p != (const MagicInfo *) NULL)
329  return(p);
330  }
331  /*
332  Search for magic tag.
333  */
334  LockSemaphoreInfo(magic_list_semaphore);
335  ResetLinkedListIterator(magic_list);
336  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
337  if (magic == (const unsigned char *) NULL)
338  {
339  UnlockSemaphoreInfo(magic_list_semaphore);
340  return(p);
341  }
342  while (p != (const MagicInfo *) NULL)
343  {
344  if (CompareMagic(magic,length,p) != MagickFalse)
345  break;
346  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
347  }
348  UnlockSemaphoreInfo(magic_list_semaphore);
349  if (p != (const MagicInfo *) NULL)
350  {
351  LockSemaphoreInfo(magic_cache_semaphore);
352  (void) InsertValueInSortedLinkedList(magic_cache,CompareMagickInfoExtent,
353  NULL,p);
354  UnlockSemaphoreInfo(magic_cache_semaphore);
355  }
356  return(p);
357 }
358 
359 /*
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 % %
362 % %
363 % %
364 % G e t M a g i c P a t t e r n E x t e n t %
365 % %
366 % %
367 % %
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 %
370 % GetMagicPatternExtent() returns the extent of the buffer that is
371 % required to check all the MagickInfos. It returns zero if the list is empty.
372 %
373 % The format of the GetMagicPatternExtent method is:
374 %
375 % size_t GetMagicPatternExtent(ExceptionInfo *exception)
376 %
377 % A description of each parameter follows:
378 %
379 % o exception: return any errors or warnings in this structure.
380 %
381 */
382 MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
383 {
384  const MagicInfo
385  *p;
386 
387  MagickOffsetType
388  max_offset,
389  offset;
390 
391  static size_t
392  extent = 0;
393 
394  assert(exception != (ExceptionInfo *) NULL);
395  if ((extent != 0) || (IsMagicListInstantiated(exception) == MagickFalse))
396  return(extent);
397  LockSemaphoreInfo(magic_list_semaphore);
398  ResetLinkedListIterator(magic_list);
399  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
400  for (max_offset=0; p != (const MagicInfo *) NULL; )
401  {
402  offset=p->offset+(MagickOffsetType) p->length;
403  if (offset > max_offset)
404  max_offset=offset;
405  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
406  }
407  if (max_offset > (MagickOffsetType) (MAGICK_SSIZE_MAX/2))
408  return(0);
409  extent=(size_t) max_offset;
410  UnlockSemaphoreInfo(magic_list_semaphore);
411  return(extent);
412 }
413 ␌
414 /*
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416 % %
417 % %
418 % %
419 % G e t M a g i c I n f o L i s t %
420 % %
421 % %
422 % %
423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424 %
425 % GetMagicInfoList() returns any image aliases that match the specified
426 % pattern.
427 %
428 % The magic of the GetMagicInfoList function is:
429 %
430 % const MagicInfo **GetMagicInfoList(const char *pattern,
431 % size_t *number_aliases,ExceptionInfo *exception)
432 %
433 % A description of each parameter follows:
434 %
435 % o pattern: Specifies a pointer to a text string containing a pattern.
436 %
437 % o number_aliases: This integer returns the number of aliases in the list.
438 %
439 % o exception: return any errors or warnings in this structure.
440 %
441 */
442 
443 #if defined(__cplusplus) || defined(c_plusplus)
444 extern "C" {
445 #endif
446 
447 static int MagicInfoCompare(const void *x,const void *y)
448 {
449  const MagicInfo
450  **p,
451  **q;
452 
453  p=(const MagicInfo **) x,
454  q=(const MagicInfo **) y;
455  return(LocaleCompare((*p)->name,(*q)->name));
456 }
457 
458 #if defined(__cplusplus) || defined(c_plusplus)
459 }
460 #endif
461 
462 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
463  size_t *number_aliases,ExceptionInfo *exception)
464 {
465  const MagicInfo
466  **aliases;
467 
468  const MagicInfo
469  *p;
470 
471  ssize_t
472  i;
473 
474  /*
475  Allocate magic list.
476  */
477  assert(pattern != (char *) NULL);
478  assert(number_aliases != (size_t *) NULL);
479  if (IsEventLogging() != MagickFalse)
480  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
481  *number_aliases=0;
482  p=GetMagicInfo((const unsigned char *) NULL,0,exception);
483  if (p == (const MagicInfo *) NULL)
484  return((const MagicInfo **) NULL);
485  aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
486  GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
487  if (aliases == (const MagicInfo **) NULL)
488  return((const MagicInfo **) NULL);
489  /*
490  Generate magic list.
491  */
492  LockSemaphoreInfo(magic_list_semaphore);
493  ResetLinkedListIterator(magic_list);
494  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
495  for (i=0; p != (const MagicInfo *) NULL; )
496  {
497  if (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)
498  aliases[i++]=p;
499  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
500  }
501  UnlockSemaphoreInfo(magic_list_semaphore);
502  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
503  aliases[i]=(MagicInfo *) NULL;
504  *number_aliases=(size_t) i;
505  return(aliases);
506 }
507 ␌
508 /*
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 % %
511 % %
512 % %
513 % G e t M a g i c L i s t %
514 % %
515 % %
516 % %
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518 %
519 % GetMagicList() returns any image format aliases that match the specified
520 % pattern.
521 %
522 % The format of the GetMagicList function is:
523 %
524 % char **GetMagicList(const char *pattern,size_t *number_aliases,
525 % ExceptionInfo *exception)
526 %
527 % A description of each parameter follows:
528 %
529 % o pattern: Specifies a pointer to a text string containing a pattern.
530 %
531 % o number_aliases: This integer returns the number of image format aliases
532 % in the list.
533 %
534 % o exception: return any errors or warnings in this structure.
535 %
536 */
537 
538 #if defined(__cplusplus) || defined(c_plusplus)
539 extern "C" {
540 #endif
541 
542 static int MagicCompare(const void *x,const void *y)
543 {
544  const char
545  *p,
546  *q;
547 
548  p=(const char *) x;
549  q=(const char *) y;
550  return(LocaleCompare(p,q));
551 }
552 
553 #if defined(__cplusplus) || defined(c_plusplus)
554 }
555 #endif
556 
557 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
558  ExceptionInfo *exception)
559 {
560  char
561  **aliases;
562 
563  const MagicInfo
564  *p;
565 
566  ssize_t
567  i;
568 
569  /*
570  Allocate configure list.
571  */
572  assert(pattern != (char *) NULL);
573  assert(number_aliases != (size_t *) NULL);
574  if (IsEventLogging() != MagickFalse)
575  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
576  *number_aliases=0;
577  p=GetMagicInfo((const unsigned char *) NULL,0,exception);
578  if (p == (const MagicInfo *) NULL)
579  return((char **) NULL);
580  aliases=(char **) AcquireQuantumMemory((size_t)
581  GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
582  if (aliases == (char **) NULL)
583  return((char **) NULL);
584  LockSemaphoreInfo(magic_list_semaphore);
585  ResetLinkedListIterator(magic_list);
586  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
587  for (i=0; p != (const MagicInfo *) NULL; )
588  {
589  if (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)
590  aliases[i++]=ConstantString(p->name);
591  p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
592  }
593  UnlockSemaphoreInfo(magic_list_semaphore);
594  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
595  aliases[i]=(char *) NULL;
596  *number_aliases=(size_t) i;
597  return(aliases);
598 }
599 ␌
600 /*
601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602 % %
603 % %
604 % %
605 % G e t M a g i c N a m e %
606 % %
607 % %
608 % %
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 %
611 % GetMagicName() returns the name associated with the magic.
612 %
613 % The format of the GetMagicName method is:
614 %
615 % const char *GetMagicName(const MagicInfo *magic_info)
616 %
617 % A description of each parameter follows:
618 %
619 % o magic_info: The magic info.
620 %
621 */
622 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
623 {
624  assert(magic_info != (MagicInfo *) NULL);
625  assert(magic_info->signature == MagickCoreSignature);
626  if (IsEventLogging() != MagickFalse)
627  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
628  return(magic_info->name);
629 }
630 ␌
631 /*
632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633 % %
634 % %
635 % %
636 + I s M a g i c L i s t I n s t a n t i a t e d %
637 % %
638 % %
639 % %
640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641 %
642 % IsMagicListInstantiated() determines if the magic list is instantiated.
643 % If not, it instantiates the list and returns it.
644 %
645 % The format of the IsMagicListInstantiated method is:
646 %
647 % MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
648 %
649 % A description of each parameter follows.
650 %
651 % o exception: return any errors or warnings in this structure.
652 %
653 */
654 static MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
655 {
656  if (magic_list == (LinkedListInfo *) NULL)
657  {
658  if (magic_list_semaphore == (SemaphoreInfo *) NULL)
659  ActivateSemaphoreInfo(&magic_list_semaphore);
660  LockSemaphoreInfo(magic_list_semaphore);
661  if (magic_list == (LinkedListInfo *) NULL)
662  magic_list=AcquireMagicList(exception);
663  UnlockSemaphoreInfo(magic_list_semaphore);
664  }
665  return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
666 }
667 ␌
668 /*
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 % %
671 % %
672 % %
673 % L i s t M a g i c I n f o %
674 % %
675 % %
676 % %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 %
679 % ListMagicInfo() lists the magic info to a file.
680 %
681 % The format of the ListMagicInfo method is:
682 %
683 % MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
684 %
685 % A description of each parameter follows.
686 %
687 % o file: An pointer to a FILE.
688 %
689 % o exception: return any errors or warnings in this structure.
690 %
691 */
692 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
693  ExceptionInfo *exception)
694 {
695  const MagicInfo
696  **magic_info;
697 
698  ssize_t
699  i;
700 
701  size_t
702  number_aliases;
703 
704  ssize_t
705  j;
706 
707  if (file == (const FILE *) NULL)
708  file=stdout;
709  magic_info=GetMagicInfoList("*",&number_aliases,exception);
710  if (magic_info == (const MagicInfo **) NULL)
711  return(MagickFalse);
712  (void) FormatLocaleFile(file,"Name Offset Target\n");
713  (void) FormatLocaleFile(file,
714  "-------------------------------------------------"
715  "------------------------------\n");
716  for (i=0; i < (ssize_t) number_aliases; i++)
717  {
718  (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
719  for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
720  (void) FormatLocaleFile(file," ");
721  (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
722  if (magic_info[i]->magic != (unsigned char *) NULL)
723  {
724  for (j=0; magic_info[i]->magic[j] != '\0'; j++)
725  if (isprint((int) (magic_info[i]->magic[j])) != 0)
726  (void) FormatLocaleFile(file,"%c",magic_info[i]->magic[j]);
727  else
728  (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
729  ((unsigned char) magic_info[i]->magic[j]));
730  }
731  (void) FormatLocaleFile(file,"\n");
732  }
733  (void) fflush(file);
734  magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
735  return(MagickTrue);
736 }
737 ␌
738 /*
739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
740 % %
741 % %
742 % %
743 + M a g i c C o m p o n e n t G e n e s i s %
744 % %
745 % %
746 % %
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748 %
749 % MagicComponentGenesis() instantiates the magic component.
750 %
751 % The format of the MagicComponentGenesis method is:
752 %
753 % MagickBooleanType MagicComponentGenesis(void)
754 %
755 */
756 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
757 {
758  if (magic_list_semaphore == (SemaphoreInfo *) NULL)
759  magic_list_semaphore=AcquireSemaphoreInfo();
760  return(MagickTrue);
761 }
762 ␌
763 /*
764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
765 % %
766 % %
767 % %
768 + M a g i c C o m p o n e n t T e r m i n u s %
769 % %
770 % %
771 % %
772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
773 %
774 % MagicComponentTerminus() destroys the magic component.
775 %
776 % The format of the MagicComponentTerminus method is:
777 %
778 % MagicComponentTerminus(void)
779 %
780 */
781 
782 static void *DestroyMagicElement(void *magic_info)
783 {
784  RelinquishMagickMemory((MagicInfo *) magic_info);
785  return((void *) NULL);
786 }
787 
788 MagickPrivate void MagicComponentTerminus(void)
789 {
790  if (magic_list_semaphore == (SemaphoreInfo *) NULL)
791  ActivateSemaphoreInfo(&magic_list_semaphore);
792  LockSemaphoreInfo(magic_list_semaphore);
793  if (magic_list != (LinkedListInfo *) NULL)
794  magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
795  UnlockSemaphoreInfo(magic_list_semaphore);
796  RelinquishSemaphoreInfo(&magic_list_semaphore);
797  if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
798  ActivateSemaphoreInfo(&magic_cache_semaphore);
799  LockSemaphoreInfo(magic_cache_semaphore);
800  if (magic_cache != (LinkedListInfo *) NULL)
801  magic_cache=DestroyLinkedList(magic_cache,(void *(*)(void *)) NULL);
802  UnlockSemaphoreInfo(magic_cache_semaphore);
803  RelinquishSemaphoreInfo(&magic_cache_semaphore);
804 }