Coverage Report

Created: 2025-08-12 07:37

/src/imagemagick/MagickCore/magic.c
Line
Count
Source (jump to first uncovered line)
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
47.2k
{
165
47.2k
  MagicInfo
166
47.2k
    *ma,
167
47.2k
    *mb;
168
169
47.2k
  MagickOffsetType
170
47.2k
    delta;
171
172
47.2k
  ma=(MagicInfo *) a;
173
47.2k
  mb=(MagicInfo *) b;
174
47.2k
  delta=(MagickOffsetType) mb->length-(MagickOffsetType) ma->length;
175
47.2k
  if (ma->offset != mb->offset)
176
15.2k
    {
177
      /*
178
        Offset is near the start? Let's search a bit further in the stream.
179
      */
180
15.2k
      delta=ma->offset-mb->offset;
181
15.2k
      if ((ma->offset > mb->offset ? ma->offset : mb->offset) <= 10)
182
13.0k
        delta=mb->offset-ma->offset;
183
15.2k
    }
184
47.2k
  return(delta > INT_MAX ? 0 : (int) delta);
185
47.2k
}
186
187
static LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
188
9
{
189
9
  LinkedListInfo
190
9
    *list;
191
192
9
  MagickStatusType
193
9
    status;
194
195
9
  ssize_t
196
9
    i;
197
198
9
  list=NewLinkedList(0);
199
9
  status=MagickTrue;
200
  /*
201
    Load built-in magic map.
202
  */
203
1.19k
  for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
204
1.18k
  {
205
1.18k
    MagicInfo
206
1.18k
      *magic_info;
207
208
1.18k
    const MagicMapInfo
209
1.18k
      *p;
210
211
1.18k
    p=MagicMap+i;
212
1.18k
    magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
213
1.18k
    if (magic_info == (MagicInfo *) NULL)
214
0
      {
215
0
        (void) ThrowMagickException(exception,GetMagickModule(),
216
0
          ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
217
0
        continue;
218
0
      }
219
1.18k
    (void) memset(magic_info,0,sizeof(*magic_info));
220
1.18k
    magic_info->name=(char *) p->name;
221
1.18k
    magic_info->offset=p->offset;
222
1.18k
    magic_info->magic=(unsigned char *) p->magic;
223
1.18k
    magic_info->length=p->length;
224
1.18k
    magic_info->skip_spaces=p->skip_spaces;
225
1.18k
    magic_info->signature=MagickCoreSignature;
226
1.18k
    status&=(MagickStatusType) InsertValueInSortedLinkedList(list,
227
1.18k
      CompareMagickInfoExtent,NULL,magic_info);
228
1.18k
    if (status == MagickFalse)
229
0
      (void) ThrowMagickException(exception,GetMagickModule(),
230
0
        ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
231
1.18k
  }
232
9
  return(list);
233
9
}
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
3.66M
{
268
3.66M
  const unsigned char
269
3.66M
    *q;
270
271
3.66M
  MagickOffsetType
272
3.66M
    remaining;
273
274
3.66M
  assert(magic_info->offset >= 0);
275
3.66M
  q=magic+magic_info->offset;
276
3.66M
  remaining=(MagickOffsetType) length-magic_info->offset;
277
3.66M
  if (magic_info->skip_spaces != MagickFalse)
278
161k
    while ((remaining > 0) && (isspace(*q) != 0))
279
11.3k
    {
280
11.3k
      q++;
281
11.3k
      remaining--;
282
11.3k
    }
283
3.66M
  if ((remaining >= (MagickOffsetType) magic_info->length) &&
284
3.66M
      (memcmp(q,magic_info->magic,magic_info->length) == 0))
285
62.6k
    return(MagickTrue);
286
3.59M
  return(MagickFalse);
287
3.66M
}
288
289
static MagickBooleanType IsMagicCacheInstantiated(void)
290
70.6k
{
291
70.6k
  if (magic_cache == (LinkedListInfo *) NULL)
292
7
    {
293
7
      if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
294
7
        ActivateSemaphoreInfo(&magic_cache_semaphore);
295
7
      LockSemaphoreInfo(magic_cache_semaphore);
296
7
      if (magic_cache == (LinkedListInfo *) NULL)
297
7
        magic_cache=NewLinkedList(0);
298
7
      UnlockSemaphoreInfo(magic_cache_semaphore);
299
7
    }
300
70.6k
  return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
301
70.6k
}
302
303
MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
304
  const size_t length,ExceptionInfo *exception)
305
70.6k
{
306
70.6k
  const MagicInfo *
307
70.6k
    magic_info;
308
309
70.6k
  ElementInfo
310
70.6k
    *p;
311
312
70.6k
  assert(exception != (ExceptionInfo *) NULL);
313
70.6k
  if (IsMagicListInstantiated(exception) == MagickFalse)
314
0
    return((const MagicInfo *) NULL);
315
70.6k
  if (IsMagicCacheInstantiated() == MagickFalse)
316
0
    return((const MagicInfo *) NULL);
317
  /*
318
    Search for cached entries.
319
  */
320
70.6k
  magic_info=(const MagicInfo *) NULL;
321
70.6k
  if (magic != (const unsigned char *) NULL)
322
70.6k
    {
323
70.6k
      LockSemaphoreInfo(magic_cache_semaphore);
324
70.6k
      p=GetHeadElementInLinkedList(magic_cache);
325
2.59M
      while (p != (ElementInfo *) NULL)
326
2.58M
      {
327
2.58M
        magic_info=(const MagicInfo *) p->value;
328
2.58M
        if (CompareMagic(magic,length,magic_info) != MagickFalse)
329
62.4k
          break;
330
2.52M
        p=p->next;
331
2.52M
      }
332
70.6k
      UnlockSemaphoreInfo(magic_cache_semaphore);
333
70.6k
      if (p != (ElementInfo *) NULL)
334
62.4k
        return(magic_info);
335
70.6k
    }
336
  /*
337
    Search for magic tag.
338
  */
339
8.23k
  LockSemaphoreInfo(magic_list_semaphore);
340
8.23k
  p=GetHeadElementInLinkedList(magic_list);
341
8.23k
  if (magic == (const unsigned char *) NULL)
342
0
    {
343
0
      UnlockSemaphoreInfo(magic_list_semaphore);
344
0
      if (p != (ElementInfo *) NULL)
345
0
        magic_info=(const MagicInfo *) p->value;
346
0
      return(magic_info);
347
0
    }
348
1.08M
  while (p != (ElementInfo *) NULL)
349
1.07M
  {
350
1.07M
    magic_info=(const MagicInfo *) p->value;
351
1.07M
    if (CompareMagic(magic,length,magic_info) != MagickFalse)
352
213
      break;
353
1.07M
    p=p->next;
354
1.07M
  }
355
8.23k
  UnlockSemaphoreInfo(magic_list_semaphore);
356
8.23k
  if (p == (ElementInfo *) NULL)
357
8.02k
    magic_info=(const MagicInfo *) NULL;
358
213
  else
359
213
    {
360
213
      LockSemaphoreInfo(magic_cache_semaphore);
361
213
      (void) InsertValueInSortedLinkedList(magic_cache,CompareMagickInfoExtent,
362
213
        NULL,magic_info);
363
213
      UnlockSemaphoreInfo(magic_cache_semaphore);
364
213
    }
365
8.23k
  return(magic_info);
366
8.23k
}
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
83.7k
{
393
83.7k
  ElementInfo
394
83.7k
    *p;
395
396
83.7k
  MagickOffsetType
397
83.7k
    max_offset,
398
83.7k
    offset;
399
400
83.7k
  static size_t
401
83.7k
    extent = 0;
402
403
83.7k
  assert(exception != (ExceptionInfo *) NULL);
404
83.7k
  if ((extent != 0) || (IsMagicListInstantiated(exception) == MagickFalse))
405
83.7k
    return(extent);
406
8
  LockSemaphoreInfo(magic_list_semaphore);
407
8
  p=GetHeadElementInLinkedList(magic_list);
408
1.06k
  for (max_offset=0; p != (ElementInfo *) NULL; )
409
1.05k
  {
410
1.05k
    const MagicInfo
411
1.05k
      *magic_info;
412
413
1.05k
    magic_info=(const MagicInfo *) p->value;
414
1.05k
    offset=magic_info->offset+(MagickOffsetType) magic_info->length;
415
1.05k
    if (offset > max_offset)
416
56
      max_offset=offset;
417
1.05k
    p=p->next;
418
1.05k
  }
419
8
  UnlockSemaphoreInfo(magic_list_semaphore);
420
8
  if (max_offset > (MagickOffsetType) (MAGICK_SSIZE_MAX/2))
421
0
    return(0);
422
8
  extent=(size_t) max_offset;
423
8
  return(extent);
424
8
}
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
0
{
461
0
  const MagicInfo
462
0
    **p,
463
0
    **q;
464
465
0
  p=(const MagicInfo **) x,
466
0
  q=(const MagicInfo **) y;
467
0
  return(LocaleCompare((*p)->name,(*q)->name));
468
0
}
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
0
{
477
0
  const MagicInfo
478
0
    **aliases;
479
480
0
  ElementInfo
481
0
    *p;
482
483
0
  ssize_t
484
0
    i;
485
486
0
  magick_unreferenced(exception);
487
0
  assert(pattern != (char *) NULL);
488
0
  assert(number_aliases != (size_t *) NULL);
489
0
  if (IsEventLogging() != MagickFalse)
490
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
491
0
  *number_aliases=0;
492
0
  if (IsMagicCacheInstantiated() == MagickFalse)
493
0
    return((const MagicInfo **) NULL);
494
0
  aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
495
0
    GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
496
0
  if (aliases == (const MagicInfo **) NULL)
497
0
    return((const MagicInfo **) NULL);
498
0
  LockSemaphoreInfo(magic_list_semaphore);
499
0
  p=GetHeadElementInLinkedList(magic_list);
500
0
  for (i=0; p != (ElementInfo *) NULL; )
501
0
  {
502
0
    const MagicInfo
503
0
      *magic_info;
504
    
505
0
    magic_info=(const MagicInfo *) p->value;
506
0
    if (GlobExpression(magic_info->name,pattern,MagickFalse) != MagickFalse)
507
0
      aliases[i++]=magic_info;
508
0
    p=p->next;
509
0
  }
510
0
  UnlockSemaphoreInfo(magic_list_semaphore);
511
0
  if (i == 0)
512
0
    aliases=(const MagicInfo **) RelinquishMagickMemory((void*) aliases);
513
0
  else
514
0
    {
515
0
      qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
516
0
      aliases[i]=(MagicInfo *) NULL;
517
0
    }
518
0
  *number_aliases=(size_t) i;
519
0
  return(aliases);
520
0
}
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
0
{
558
0
  const char
559
0
    *p,
560
0
    *q;
561
562
0
  p=(const char *) x;
563
0
  q=(const char *) y;
564
0
  return(LocaleCompare(p,q));
565
0
}
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
0
{
574
0
  char
575
0
    **aliases;
576
577
0
  ElementInfo
578
0
    *p;
579
580
0
  ssize_t
581
0
    i;
582
  
583
0
  magick_unreferenced(exception);
584
0
  assert(pattern != (char *) NULL);
585
0
  assert(number_aliases != (size_t *) NULL);
586
0
  if (IsEventLogging() != MagickFalse)
587
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
588
0
  *number_aliases=0;
589
0
  if (IsMagicCacheInstantiated() == MagickFalse)
590
0
    return((char **) NULL);
591
0
  aliases=(char **) AcquireQuantumMemory((size_t)
592
0
    GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
593
0
  if (aliases == (char **) NULL)
594
0
    return((char **) NULL);
595
0
  LockSemaphoreInfo(magic_list_semaphore);
596
0
  p=GetHeadElementInLinkedList(magic_list);
597
0
  for (i=0; p != (ElementInfo *) NULL; )
598
0
  {
599
0
    const MagicInfo
600
0
      *magic_info;
601
602
0
    magic_info=(const MagicInfo *) p->value;
603
0
    if (GlobExpression(magic_info->name,pattern,MagickFalse) != MagickFalse)
604
0
      aliases[i++]=ConstantString(magic_info->name);
605
0
    p=p->next;
606
0
  }
607
0
  UnlockSemaphoreInfo(magic_list_semaphore);
608
0
  if (i == 0)
609
0
    aliases=(char **) RelinquishMagickMemory(aliases);
610
0
  else
611
0
    {
612
0
      qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
613
0
      aliases[i]=(char *) NULL;
614
0
    }
615
0
  *number_aliases=(size_t) i;
616
0
  return(aliases);
617
0
}
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
125k
{
643
125k
  assert(magic_info != (MagicInfo *) NULL);
644
125k
  assert(magic_info->signature == MagickCoreSignature);
645
125k
  if (IsEventLogging() != MagickFalse)
646
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
647
125k
  return(magic_info->name);
648
125k
}
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
70.7k
{
675
70.7k
  if (magic_list == (LinkedListInfo *) NULL)
676
9
    {
677
9
      if (magic_list_semaphore == (SemaphoreInfo *) NULL)
678
0
        ActivateSemaphoreInfo(&magic_list_semaphore);
679
9
      LockSemaphoreInfo(magic_list_semaphore);
680
9
      if (magic_list == (LinkedListInfo *) NULL)
681
9
        magic_list=AcquireMagicList(exception);
682
9
      UnlockSemaphoreInfo(magic_list_semaphore);
683
9
    }
684
70.7k
  return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
685
70.7k
}
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
0
{
714
0
  const MagicInfo
715
0
    **magic_info;
716
717
0
  ssize_t
718
0
    i;
719
720
0
  size_t
721
0
    number_aliases;
722
723
0
  ssize_t
724
0
    j;
725
726
0
  if (file == (const FILE *) NULL)
727
0
    file=stdout;
728
0
  magic_info=GetMagicInfoList("*",&number_aliases,exception);
729
0
  if (magic_info == (const MagicInfo **) NULL)
730
0
    return(MagickFalse);
731
0
  (void) FormatLocaleFile(file,"Name      Offset Target\n");
732
0
  (void) FormatLocaleFile(file,
733
0
    "-------------------------------------------------"
734
0
    "------------------------------\n");
735
0
  for (i=0; i < (ssize_t) number_aliases; i++)
736
0
  {
737
0
    (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
738
0
    for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
739
0
      (void) FormatLocaleFile(file," ");
740
0
    (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
741
0
    if (magic_info[i]->magic != (unsigned char *) NULL)
742
0
      {
743
0
        for (j=0; magic_info[i]->magic[j] != '\0'; j++)
744
0
          if (isprint((int) (magic_info[i]->magic[j])) != 0)
745
0
            (void) FormatLocaleFile(file,"%c",magic_info[i]->magic[j]);
746
0
          else
747
0
            (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
748
0
              ((unsigned char) magic_info[i]->magic[j]));
749
0
      }
750
0
    (void) FormatLocaleFile(file,"\n");
751
0
  }
752
0
  (void) fflush(file);
753
0
  magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
754
0
  return(MagickTrue);
755
0
}
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
294
{
777
294
  if (magic_list_semaphore == (SemaphoreInfo *) NULL)
778
294
    magic_list_semaphore=AcquireSemaphoreInfo();
779
294
  return(MagickTrue);
780
294
}
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
0
{
803
0
  (void) RelinquishMagickMemory((MagicInfo *) magic_info);
804
0
  return((void *) NULL);
805
0
}
806
807
MagickPrivate void MagicComponentTerminus(void)
808
0
{
809
0
  if (magic_list_semaphore == (SemaphoreInfo *) NULL)
810
0
    ActivateSemaphoreInfo(&magic_list_semaphore);
811
0
  LockSemaphoreInfo(magic_list_semaphore);
812
0
  if (magic_list != (LinkedListInfo *) NULL)
813
0
    magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
814
0
  UnlockSemaphoreInfo(magic_list_semaphore);
815
0
  RelinquishSemaphoreInfo(&magic_list_semaphore);
816
0
  if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
817
0
    ActivateSemaphoreInfo(&magic_cache_semaphore);
818
0
  LockSemaphoreInfo(magic_cache_semaphore);
819
0
  if (magic_cache != (LinkedListInfo *) NULL)
820
0
    magic_cache=DestroyLinkedList(magic_cache,(void *(*)(void *)) NULL);
821
0
  UnlockSemaphoreInfo(magic_cache_semaphore);
822
0
  RelinquishSemaphoreInfo(&magic_cache_semaphore);
823
0
}