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