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