MagickCore 7.1.1
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
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/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*/
71typedef 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;
88
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*/
113static 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
123static LinkedListInfo
124 *magic_cache = (LinkedListInfo *) NULL,
125 *magic_list = (LinkedListInfo *) NULL;
126
127static SemaphoreInfo
128 *magic_cache_semaphore = (SemaphoreInfo *) NULL,
129 *magic_list_semaphore = (SemaphoreInfo *) NULL;
130
131/*
132 Forward declarations.
133*/
134static 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
163static 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
187static LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
188{
189 LinkedListInfo
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
265static 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
289static 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
303MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
304 const size_t length,ExceptionInfo *exception)
305{
306 const MagicInfo *
307 magic_info;
308
309 ElementInfo
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*/
391MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
392{
393 ElementInfo
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)
456extern "C" {
457#endif
458
459static 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
474MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
475 size_t *number_aliases,ExceptionInfo *magick_unused(exception))
476{
477 const MagicInfo
478 **aliases;
479
480 ElementInfo
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)
553extern "C" {
554#endif
555
556static 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
571MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
572 ExceptionInfo *magick_unused(exception))
573{
574 char
575 **aliases;
576
577 ElementInfo
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*/
641MagickExport 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*/
673static 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*/
711MagickExport 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*/
775MagickPrivate 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
801static void *DestroyMagicElement(void *magic_info)
802{
803 RelinquishMagickMemory((MagicInfo *) magic_info);
804 return((void *) NULL);
805}
806
807MagickPrivate 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}