blob: f63573bc8163cfb0148734c76a2369e890afee13 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
cristyb1860752011-03-14 00:27:46 +00005% %
cristy3ed852e2009-09-05 21:47:34 +00006% 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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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% http://www.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*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/client.h"
45#include "MagickCore/configure.h"
cristy9639ba32011-09-05 15:09:42 +000046#include "MagickCore/configure-private.h"
cristy4c08aed2011-07-01 19:47:50 +000047#include "MagickCore/exception.h"
48#include "MagickCore/exception-private.h"
49#include "MagickCore/hashmap.h"
50#include "MagickCore/magic.h"
cristy5ff4eaf2011-09-03 01:38:02 +000051#include "MagickCore/magic-private.h"
cristy4c08aed2011-07-01 19:47:50 +000052#include "MagickCore/memory_.h"
53#include "MagickCore/semaphore.h"
54#include "MagickCore/string_.h"
55#include "MagickCore/string-private.h"
56#include "MagickCore/token.h"
57#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000058#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000059#include "MagickCore/xml-tree.h"
cristy3ed852e2009-09-05 21:47:34 +000060
61/*
62 Define declarations.
63*/
64#define MagicFilename "magic.xml"
cristy54a531d2009-10-21 17:58:01 +000065#define MagickString(magic) (const unsigned char *) (magic), sizeof(magic)-1
cristy3ed852e2009-09-05 21:47:34 +000066
67/*
cristy54a531d2009-10-21 17:58:01 +000068 Typedef declarations.
cristy3ed852e2009-09-05 21:47:34 +000069*/
cristy1ca3eb32009-10-15 18:41:54 +000070typedef struct _MagicMapInfo
71{
72 const char
73 *name;
74
cristye3e77a12009-10-16 00:47:21 +000075 const MagickOffsetType
76 offset;
77
cristybcdce3d2009-10-15 20:04:49 +000078 const unsigned char
cristy1ca3eb32009-10-15 18:41:54 +000079 *magic;
80
cristye3e77a12009-10-16 00:47:21 +000081 const size_t
cristy1ca3eb32009-10-15 18:41:54 +000082 length;
cristy1ca3eb32009-10-15 18:41:54 +000083} MagicMapInfo;
cristy54a531d2009-10-21 17:58:01 +000084
85/*
86 Static declarations.
87*/
cristy1ca3eb32009-10-15 18:41:54 +000088static const MagicMapInfo
89 MagicMap[] =
90 {
cristye3e77a12009-10-16 00:47:21 +000091 { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
92 { "8BIMTEXT", 0, MagickString("8BIM#") },
93 { "8BIM", 0, MagickString("8BIM") },
94 { "BMP", 0, MagickString("BA") },
95 { "BMP", 0, MagickString("BM") },
96 { "BMP", 0, MagickString("CI") },
97 { "BMP", 0, MagickString("CP") },
98 { "BMP", 0, MagickString("IC") },
99 { "BMP", 0, MagickString("PI") },
100 { "CALS", 21, MagickString("version: MIL-STD-1840") },
101 { "CALS", 0, MagickString("srcdocid:") },
102 { "CALS", 9, MagickString("srcdocid:") },
103 { "CALS", 8, MagickString("rorient:") },
104 { "CGM", 0, MagickString("BEGMF") },
105 { "CIN", 0, MagickString("\200\052\137\327") },
106 { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
107 { "DCM", 128, MagickString("DICM") },
108 { "DCX", 0, MagickString("\261\150\336\72") },
109 { "DIB", 0, MagickString("\050\000") },
110 { "DDS", 0, MagickString("DDS ") },
111 { "DJVU", 0, MagickString("AT&TFORM") },
112 { "DOT", 0, MagickString("digraph") },
113 { "DPX", 0, MagickString("SDPX") },
114 { "DPX", 0, MagickString("XPDS") },
115 { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
116 { "EPT", 0, MagickString("\305\320\323\306") },
117 { "EXR", 0, MagickString("\166\057\061\001") },
118 { "FAX", 0, MagickString("DFAX") },
119 { "FIG", 0, MagickString("#FIG") },
120 { "FITS", 0, MagickString("IT0") },
121 { "FITS", 0, MagickString("SIMPLE") },
122 { "FPX", 0, MagickString("\320\317\021\340") },
123 { "GIF", 0, MagickString("GIF8") },
124 { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
125 { "HDF", 1, MagickString("HDF") },
cristy03533f22011-03-06 23:30:17 +0000126 { "HDR", 0, MagickString("#?RADIANCE") },
cristy84c3d052011-03-07 19:22:02 +0000127 { "HDR", 0, MagickString("#?RGBE") },
cristye3e77a12009-10-16 00:47:21 +0000128 { "HPGL", 0, MagickString("IN;") },
cristye3e77a12009-10-16 00:47:21 +0000129 { "HTML", 1, MagickString("HTML") },
130 { "HTML", 1, MagickString("html") },
131 { "ILBM", 8, MagickString("ILBM") },
132 { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
133 { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
134 { "IPTC", 0, MagickString("\034\002") },
135 { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
136 { "JPEG", 0, MagickString("\377\330\377") },
137 { "JPC", 0, MagickString("\377\117") },
138 { "JP2", 4, MagickString("\152\120\040\040\015") },
cristya7cb4312010-06-26 00:47:03 +0000139 { "MAT", 0, MagickString("MATLAB 5.0 MAT-file,") },
cristye3e77a12009-10-16 00:47:21 +0000140 { "MIFF", 0, MagickString("Id=ImageMagick") },
141 { "MIFF", 0, MagickString("id=ImageMagick") },
142 { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
143 { "MPC", 0, MagickString("id=MagickCache") },
144 { "MPEG", 0, MagickString("\000\000\001\263") },
145 { "MRW", 0, MagickString("\x00MRM") },
146 { "MVG", 0, MagickString("push graphic-context") },
147 { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
148 { "PCD", 2048, MagickString("PCD_") },
149 { "PCL", 0, MagickString("\033E\033") },
150 { "PCX", 0, MagickString("\012\002") },
151 { "PCX", 0, MagickString("\012\005") },
152 { "PDB", 60, MagickString("vIMGView") },
153 { "PDF", 0, MagickString("%PDF-") },
cristy7adb4db2010-01-24 17:14:03 +0000154 { "PES", 0, MagickString("#PES") },
cristye3e77a12009-10-16 00:47:21 +0000155 { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
156 { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
157 { "PGX", 0, MagickString("\050\107\020\115\046") },
158 { "PICT", 522, MagickString("\000\021\002\377\014\000") },
159 { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
cristy34575212010-11-06 12:39:23 +0000160 { "PBM", 0, MagickString("P1") },
161 { "PGM", 0, MagickString("P2") },
162 { "PPM", 0, MagickString("P3") },
163 { "PBM", 0, MagickString("P4") },
164 { "PGM", 0, MagickString("P5") },
165 { "PPM", 0, MagickString("P6") },
166 { "PAM", 0, MagickString("P7") },
167 { "PFM", 0, MagickString("PF") },
168 { "PFM", 0, MagickString("Pf") },
cristye3e77a12009-10-16 00:47:21 +0000169 { "PS", 0, MagickString("%!") },
170 { "PS", 0, MagickString("\004%!") },
171 { "PS", 0, MagickString("\305\320\323\306") },
cristyb4233012010-02-28 20:09:14 +0000172 { "PSB", 0, MagickString("8BPB") },
cristye3e77a12009-10-16 00:47:21 +0000173 { "PSD", 0, MagickString("8BPS") },
174 { "PWP", 0, MagickString("SFW95") },
175 { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
cristye3e77a12009-10-16 00:47:21 +0000176 { "RLE", 0, MagickString("\122\314") },
177 { "SCT", 0, MagickString("CT") },
178 { "SFW", 0, MagickString("SFW94") },
179 { "SGI", 0, MagickString("\001\332") },
180 { "SUN", 0, MagickString("\131\246\152\225") },
181 { "SVG", 1, MagickString("?XML") },
182 { "SVG", 1, MagickString("?xml") },
183 { "TIFF", 0, MagickString("\115\115\000\052") },
184 { "TIFF", 0, MagickString("\111\111\052\000") },
185 { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
186 { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
187 { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
188 { "VICAR", 0, MagickString("LBLSIZE") },
189 { "VICAR", 0, MagickString("NJPL1I") },
190 { "VIFF", 0, MagickString("\253\001") },
cristy56dd2cd2010-10-11 00:45:14 +0000191 { "WEBP", 8, MagickString("WEBP") },
cristye3e77a12009-10-16 00:47:21 +0000192 { "WMF", 0, MagickString("\327\315\306\232") },
193 { "WMF", 0, MagickString("\001\000\011\000") },
194 { "WPG", 0, MagickString("\377WPC") },
195 { "XBM", 0, MagickString("#define") },
196 { "XCF", 0, MagickString("gimp xcf") },
197 { "XEF", 0, MagickString("FOVb") },
198 { "XPM", 1, MagickString("* XPM *") },
199 { "XWD", 4, MagickString("\007\000\000") },
cristy54a531d2009-10-21 17:58:01 +0000200 { "XWD", 5, MagickString("\000\000\007") }
cristy1ca3eb32009-10-15 18:41:54 +0000201 };
cristy3ed852e2009-09-05 21:47:34 +0000202
203static LinkedListInfo
204 *magic_list = (LinkedListInfo *) NULL;
205
206static SemaphoreInfo
207 *magic_semaphore = (SemaphoreInfo *) NULL;
208
209static volatile MagickBooleanType
210 instantiate_magic = MagickFalse;
211
212/*
213 Forward declarations.
214*/
215static MagickBooleanType
216 InitializeMagicList(ExceptionInfo *),
217 LoadMagicLists(const char *,ExceptionInfo *);
218
219/*
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221% %
222% %
223% %
cristy3ed852e2009-09-05 21:47:34 +0000224+ G e t M a g i c I n f o %
225% %
226% %
227% %
228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229%
230% GetMagicInfo() searches the magic list for the specified name and if found
231% returns attributes for that magic.
232%
233% The format of the GetMagicInfo method is:
234%
235% const MagicInfo *GetMagicInfo(const unsigned char *magic,
236% const size_t length,ExceptionInfo *exception)
237%
238% A description of each parameter follows:
239%
240% o magic: A binary string generally representing the first few characters
241% of the image file or blob.
242%
243% o length: the length of the binary signature.
244%
245% o exception: return any errors or warnings in this structure.
246%
247*/
248MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
249 const size_t length,ExceptionInfo *exception)
250{
251 register const MagicInfo
252 *p;
253
254 assert(exception != (ExceptionInfo *) NULL);
255 if ((magic_list == (LinkedListInfo *) NULL) ||
256 (instantiate_magic == MagickFalse))
257 if (InitializeMagicList(exception) == MagickFalse)
258 return((const MagicInfo *) NULL);
259 if ((magic_list == (LinkedListInfo *) NULL) ||
260 (IsLinkedListEmpty(magic_list) != MagickFalse))
261 return((const MagicInfo *) NULL);
262 if (magic == (const unsigned char *) NULL)
263 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
264 if (length == 0)
265 return((const MagicInfo *) NULL);
266 /*
267 Search for magic tag.
268 */
cristyf84a1932010-01-03 18:00:18 +0000269 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000270 ResetLinkedListIterator(magic_list);
271 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
272 while (p != (const MagicInfo *) NULL)
273 {
274 assert(p->offset >= 0);
275 if (((size_t) (p->offset+p->length) <= length) &&
276 (memcmp(magic+p->offset,p->magic,p->length) == 0))
277 break;
278 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
279 }
280 if (p != (const MagicInfo *) NULL)
281 (void) InsertValueInLinkedList(magic_list,0,
282 RemoveElementByValueFromLinkedList(magic_list,p));
cristyf84a1932010-01-03 18:00:18 +0000283 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000284 return(p);
285}
286
287/*
288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289% %
290% %
291% %
292% G e t M a g i c I n f o L i s t %
293% %
294% %
295% %
296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297%
298% GetMagicInfoList() returns any image aliases that match the specified
299% pattern.
300%
301% The magic of the GetMagicInfoList function is:
302%
303% const MagicInfo **GetMagicInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000304% size_t *number_aliases,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000305%
306% A description of each parameter follows:
307%
308% o pattern: Specifies a pointer to a text string containing a pattern.
309%
cristyfc0d1122009-10-17 20:22:37 +0000310% o number_aliases: This integer returns the number of aliases in the list.
cristy3ed852e2009-09-05 21:47:34 +0000311%
312% o exception: return any errors or warnings in this structure.
313%
314*/
315
316#if defined(__cplusplus) || defined(c_plusplus)
317extern "C" {
318#endif
319
320static int MagicInfoCompare(const void *x,const void *y)
321{
322 const MagicInfo
323 **p,
324 **q;
325
326 p=(const MagicInfo **) x,
327 q=(const MagicInfo **) y;
328 if (LocaleCompare((*p)->path,(*q)->path) == 0)
329 return(LocaleCompare((*p)->name,(*q)->name));
330 return(LocaleCompare((*p)->path,(*q)->path));
331}
332
333#if defined(__cplusplus) || defined(c_plusplus)
334}
335#endif
336
337MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000338 size_t *number_aliases,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000339{
340 const MagicInfo
341 **aliases;
342
343 register const MagicInfo
344 *p;
345
cristybb503372010-05-27 20:51:26 +0000346 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000347 i;
348
349 /*
350 Allocate magic list.
351 */
352 assert(pattern != (char *) NULL);
353 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000354 assert(number_aliases != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000355 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000356 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000357 if (p == (const MagicInfo *) NULL)
358 return((const MagicInfo **) NULL);
359 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
360 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
361 if (aliases == (const MagicInfo **) NULL)
362 return((const MagicInfo **) NULL);
363 /*
364 Generate magic list.
365 */
cristyf84a1932010-01-03 18:00:18 +0000366 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000367 ResetLinkedListIterator(magic_list);
368 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
369 for (i=0; p != (const MagicInfo *) NULL; )
370 {
371 if ((p->stealth == MagickFalse) &&
372 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
373 aliases[i++]=p;
374 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
375 }
cristyf84a1932010-01-03 18:00:18 +0000376 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000377 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
378 aliases[i]=(MagicInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000379 *number_aliases=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000380 return(aliases);
381}
382
383/*
384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385% %
386% %
387% %
388% G e t M a g i c L i s t %
389% %
390% %
391% %
392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393%
394% GetMagicList() returns any image format aliases that match the specified
395% pattern.
396%
397% The format of the GetMagicList function is:
398%
cristybb503372010-05-27 20:51:26 +0000399% char **GetMagicList(const char *pattern,size_t *number_aliases,
cristy3ed852e2009-09-05 21:47:34 +0000400% ExceptionInfo *exception)
401%
402% A description of each parameter follows:
403%
404% o pattern: Specifies a pointer to a text string containing a pattern.
405%
406% o number_aliases: This integer returns the number of image format aliases
407% in the list.
408%
409% o exception: return any errors or warnings in this structure.
410%
411*/
412
413#if defined(__cplusplus) || defined(c_plusplus)
414extern "C" {
415#endif
416
417static int MagicCompare(const void *x,const void *y)
418{
419 register const char
420 *p,
421 *q;
422
423 p=(const char *) x;
424 q=(const char *) y;
425 return(LocaleCompare(p,q));
426}
427
428#if defined(__cplusplus) || defined(c_plusplus)
429}
430#endif
431
432MagickExport char **GetMagicList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000433 size_t *number_aliases,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000434{
435 char
436 **aliases;
437
438 register const MagicInfo
439 *p;
440
cristybb503372010-05-27 20:51:26 +0000441 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000442 i;
443
444 /*
445 Allocate configure list.
446 */
447 assert(pattern != (char *) NULL);
448 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000449 assert(number_aliases != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000450 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000451 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000452 if (p == (const MagicInfo *) NULL)
453 return((char **) NULL);
454 aliases=(char **) AcquireQuantumMemory((size_t)
455 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
456 if (aliases == (char **) NULL)
457 return((char **) NULL);
cristyf84a1932010-01-03 18:00:18 +0000458 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000459 ResetLinkedListIterator(magic_list);
460 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
461 for (i=0; p != (const MagicInfo *) NULL; )
462 {
463 if ((p->stealth == MagickFalse) &&
464 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
465 aliases[i++]=ConstantString(p->name);
466 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
467 }
cristyf84a1932010-01-03 18:00:18 +0000468 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000469 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
470 aliases[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000471 *number_aliases=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000472 return(aliases);
473}
474
475/*
476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477% %
478% %
479% %
480% G e t M a g i c N a m e %
481% %
482% %
483% %
484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485%
486% GetMagicName() returns the name associated with the magic.
487%
488% The format of the GetMagicName method is:
489%
490% const char *GetMagicName(const MagicInfo *magic_info)
491%
492% A description of each parameter follows:
493%
494% o magic_info: The magic info.
495%
496*/
497MagickExport const char *GetMagicName(const MagicInfo *magic_info)
498{
499 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
500 assert(magic_info != (MagicInfo *) NULL);
501 assert(magic_info->signature == MagickSignature);
502 return(magic_info->name);
503}
504
505/*
506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507% %
508% %
509% %
510+ I n i t i a l i z e M a g i c L i s t %
511% %
512% %
513% %
514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515%
516% InitializeMagicList() initializes the magic list.
517%
518% The format of the InitializeMagicList method is:
519%
520% MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
521%
522% A description of each parameter follows.
523%
524% o exception: return any errors or warnings in this structure.
525%
526*/
527static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
528{
529 if ((magic_list == (LinkedListInfo *) NULL) &&
530 (instantiate_magic == MagickFalse))
531 {
cristy4e1dff62009-10-25 20:36:03 +0000532 if (magic_semaphore == (SemaphoreInfo *) NULL)
533 AcquireSemaphoreInfo(&magic_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000534 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000535 if ((magic_list == (LinkedListInfo *) NULL) &&
536 (instantiate_magic == MagickFalse))
537 {
538 (void) LoadMagicLists(MagicFilename,exception);
539 instantiate_magic=MagickTrue;
540 }
cristyf84a1932010-01-03 18:00:18 +0000541 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000542 }
543 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
544}
545
546/*
547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
548% %
549% %
550% %
551% L i s t M a g i c I n f o %
552% %
553% %
554% %
555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556%
557% ListMagicInfo() lists the magic info to a file.
558%
559% The format of the ListMagicInfo method is:
560%
561% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
562%
563% A description of each parameter follows.
564%
565% o file: An pointer to a FILE.
566%
567% o exception: return any errors or warnings in this structure.
568%
569*/
570MagickExport MagickBooleanType ListMagicInfo(FILE *file,
571 ExceptionInfo *exception)
572{
573 const char
574 *path;
575
576 const MagicInfo
577 **magic_info;
578
cristybb503372010-05-27 20:51:26 +0000579 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000580 i;
581
cristybb503372010-05-27 20:51:26 +0000582 size_t
cristy3ed852e2009-09-05 21:47:34 +0000583 number_aliases;
584
cristy9d314ff2011-03-09 01:30:28 +0000585 ssize_t
586 j;
587
cristy3ed852e2009-09-05 21:47:34 +0000588 if (file == (const FILE *) NULL)
589 file=stdout;
590 magic_info=GetMagicInfoList("*",&number_aliases,exception);
591 if (magic_info == (const MagicInfo **) NULL)
592 return(MagickFalse);
593 j=0;
594 path=(const char *) NULL;
cristybb503372010-05-27 20:51:26 +0000595 for (i=0; i < (ssize_t) number_aliases; i++)
cristy3ed852e2009-09-05 21:47:34 +0000596 {
597 if (magic_info[i]->stealth != MagickFalse)
598 continue;
599 if ((path == (const char *) NULL) ||
600 (LocaleCompare(path,magic_info[i]->path) != 0))
601 {
602 if (magic_info[i]->path != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000603 (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
604 (void) FormatLocaleFile(file,"Name Offset Target\n");
cristy1e604812011-05-19 18:07:50 +0000605 (void) FormatLocaleFile(file,
606 "-------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +0000607 "------------------------------\n");
608 }
609 path=magic_info[i]->path;
cristyb51dff52011-05-19 16:55:47 +0000610 (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
cristybb503372010-05-27 20:51:26 +0000611 for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
cristyb51dff52011-05-19 16:55:47 +0000612 (void) FormatLocaleFile(file," ");
613 (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
cristy3ed852e2009-09-05 21:47:34 +0000614 if (magic_info[i]->target != (char *) NULL)
cristy1ca3eb32009-10-15 18:41:54 +0000615 {
cristybb503372010-05-27 20:51:26 +0000616 register ssize_t
cristy1ca3eb32009-10-15 18:41:54 +0000617 j;
618
619 for (j=0; magic_info[i]->target[j] != '\0'; j++)
620 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
cristyb51dff52011-05-19 16:55:47 +0000621 (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
cristy1ca3eb32009-10-15 18:41:54 +0000622 else
cristyb51dff52011-05-19 16:55:47 +0000623 (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
cristy50931922009-10-15 18:59:59 +0000624 ((unsigned char) magic_info[i]->target[j]));
cristy1ca3eb32009-10-15 18:41:54 +0000625 }
cristyb51dff52011-05-19 16:55:47 +0000626 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +0000627 }
628 (void) fflush(file);
629 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
630 return(MagickTrue);
631}
632
633/*
634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635% %
636% %
637% %
638+ L o a d M a g i c L i s t %
639% %
640% %
641% %
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643%
644% LoadMagicList() loads the magic configuration file which provides a mapping
645% between magic attributes and a magic name.
646%
647% The format of the LoadMagicList method is:
648%
649% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000650% const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000651%
652% A description of each parameter follows:
653%
cristy1ca3eb32009-10-15 18:41:54 +0000654% o xml: The magic list in XML format.
cristy3ed852e2009-09-05 21:47:34 +0000655%
cristy1ca3eb32009-10-15 18:41:54 +0000656% o filename: The magic list filename.
cristy3ed852e2009-09-05 21:47:34 +0000657%
658% o depth: depth of <include /> statements.
659%
660% o exception: return any errors or warnings in this structure.
661%
662*/
663static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000664 const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000665{
666 char
667 keyword[MaxTextExtent],
668 *token;
669
670 const char
671 *q;
672
673 MagickBooleanType
674 status;
675
676 MagicInfo
677 *magic_info;
678
679 /*
680 Load the magic map file.
681 */
682 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
683 "Loading magic configure file \"%s\" ...",filename);
684 if (xml == (char *) NULL)
685 return(MagickFalse);
686 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000687 {
688 magic_list=NewLinkedList(0);
689 if (magic_list == (LinkedListInfo *) NULL)
690 {
691 ThrowFileException(exception,ResourceLimitError,
692 "MemoryAllocationFailed",filename);
693 return(MagickFalse);
694 }
695 }
cristy3ed852e2009-09-05 21:47:34 +0000696 status=MagickTrue;
697 magic_info=(MagicInfo *) NULL;
698 token=AcquireString(xml);
699 for (q=(char *) xml; *q != '\0'; )
700 {
701 /*
702 Interpret XML.
703 */
704 GetMagickToken(q,&q,token);
705 if (*token == '\0')
706 break;
707 (void) CopyMagickString(keyword,token,MaxTextExtent);
708 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
709 {
710 /*
711 Doctype element.
712 */
713 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
714 GetMagickToken(q,&q,token);
715 continue;
716 }
717 if (LocaleNCompare(keyword,"<!--",4) == 0)
718 {
719 /*
720 Comment element.
721 */
722 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
723 GetMagickToken(q,&q,token);
724 continue;
725 }
726 if (LocaleCompare(keyword,"<include") == 0)
727 {
728 /*
729 Include element.
730 */
731 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
732 {
733 (void) CopyMagickString(keyword,token,MaxTextExtent);
734 GetMagickToken(q,&q,token);
735 if (*token != '=')
736 continue;
737 GetMagickToken(q,&q,token);
738 if (LocaleCompare(keyword,"file") == 0)
739 {
740 if (depth > 200)
741 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000742 ConfigureError,"IncludeElementNestedTooDeeply","'%s'",token);
cristy3ed852e2009-09-05 21:47:34 +0000743 else
744 {
745 char
746 path[MaxTextExtent],
747 *xml;
748
749 GetPathComponent(filename,HeadPath,path);
750 if (*path != '\0')
751 (void) ConcatenateMagickString(path,DirectorySeparator,
752 MaxTextExtent);
753 if (*token == *DirectorySeparator)
754 (void) CopyMagickString(path,token,MaxTextExtent);
755 else
756 (void) ConcatenateMagickString(path,token,MaxTextExtent);
757 xml=FileToString(path,~0,exception);
758 if (xml != (char *) NULL)
759 {
760 status=LoadMagicList(xml,path,depth+1,exception);
761 xml=(char *) RelinquishMagickMemory(xml);
762 }
763 }
764 }
765 }
766 continue;
767 }
768 if (LocaleCompare(keyword,"<magic") == 0)
769 {
770 /*
771 Magic element.
772 */
cristy73bd4a52010-10-05 11:24:23 +0000773 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
cristy3ed852e2009-09-05 21:47:34 +0000774 if (magic_info == (MagicInfo *) NULL)
775 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
776 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
777 magic_info->path=ConstantString(filename);
cristye3e77a12009-10-16 00:47:21 +0000778 magic_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000779 magic_info->signature=MagickSignature;
780 continue;
781 }
782 if (magic_info == (MagicInfo *) NULL)
783 continue;
784 if (LocaleCompare(keyword,"/>") == 0)
785 {
786 status=AppendValueToLinkedList(magic_list,magic_info);
787 if (status == MagickFalse)
788 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000789 ResourceLimitError,"MemoryAllocationFailed","'%s'",
cristy3ed852e2009-09-05 21:47:34 +0000790 magic_info->name);
791 magic_info=(MagicInfo *) NULL;
792 }
793 GetMagickToken(q,(const char **) NULL,token);
794 if (*token != '=')
795 continue;
796 GetMagickToken(q,&q,token);
797 GetMagickToken(q,&q,token);
798 switch (*keyword)
799 {
800 case 'N':
801 case 'n':
802 {
803 if (LocaleCompare((char *) keyword,"name") == 0)
804 {
805 magic_info->name=ConstantString(token);
806 break;
807 }
808 break;
809 }
810 case 'O':
811 case 'o':
812 {
813 if (LocaleCompare((char *) keyword,"offset") == 0)
814 {
cristyf2f27272009-12-17 14:48:46 +0000815 magic_info->offset=(MagickOffsetType) StringToLong(token);
cristy3ed852e2009-09-05 21:47:34 +0000816 break;
817 }
818 break;
819 }
820 case 'S':
821 case 's':
822 {
823 if (LocaleCompare((char *) keyword,"stealth") == 0)
824 {
anthony6f201312012-03-30 04:08:15 +0000825 magic_info->stealth=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +0000826 break;
827 }
828 break;
829 }
830 case 'T':
831 case 't':
832 {
833 if (LocaleCompare((char *) keyword,"target") == 0)
834 {
835 char
836 *p;
837
838 register unsigned char
839 *q;
840
841 size_t
842 length;
843
844 length=strlen(token);
845 magic_info->target=ConstantString(token);
846 magic_info->magic=(unsigned char *) ConstantString(token);
847 q=magic_info->magic;
848 for (p=magic_info->target; *p != '\0'; )
849 {
850 if (*p == '\\')
851 {
852 p++;
853 if (isdigit((int) ((unsigned char) *p)) != 0)
854 {
855 char
856 *end;
857
858 *q++=(unsigned char) strtol(p,&end,8);
859 p+=(end-p);
860 magic_info->length++;
861 continue;
862 }
863 switch (*p)
864 {
865 case 'b': *q='\b'; break;
866 case 'f': *q='\f'; break;
867 case 'n': *q='\n'; break;
868 case 'r': *q='\r'; break;
869 case 't': *q='\t'; break;
870 case 'v': *q='\v'; break;
871 case 'a': *q='a'; break;
872 case '?': *q='\?'; break;
873 default: *q=(unsigned char) (*p); break;
874 }
875 p++;
876 q++;
877 magic_info->length++;
878 continue;
879 }
880 else
881 if (LocaleNCompare(p,"&amp;",5) == 0)
882 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
883 *q++=(unsigned char) (*p++);
884 magic_info->length++;
885 }
886 break;
887 }
888 break;
889 }
890 default:
891 break;
892 }
893 }
894 token=(char *) RelinquishMagickMemory(token);
895 return(status);
896}
897
898/*
899%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900% %
901% %
902% %
903% L o a d M a g i c L i s t s %
904% %
905% %
906% %
907%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908%
909% LoadMagicLists() loads one or more magic configuration file which provides a
910% mapping between magic attributes and a magic name.
911%
912% The format of the LoadMagicLists method is:
913%
914% MagickBooleanType LoadMagicLists(const char *filename,
915% ExceptionInfo *exception)
916%
917% A description of each parameter follows:
918%
919% o filename: the font file name.
920%
921% o exception: return any errors or warnings in this structure.
922%
923*/
924static MagickBooleanType LoadMagicLists(const char *filename,
925 ExceptionInfo *exception)
926{
cristy3ed852e2009-09-05 21:47:34 +0000927 char
928 path[MaxTextExtent];
929
930 const StringInfo
931 *option;
932
933 LinkedListInfo
934 *options;
935
936 MagickStatusType
937 status;
938
cristybb503372010-05-27 20:51:26 +0000939 register ssize_t
cristy54a531d2009-10-21 17:58:01 +0000940 i;
cristy1ca3eb32009-10-15 18:41:54 +0000941
942 /*
943 Load built-in magic map.
944 */
cristy3ed852e2009-09-05 21:47:34 +0000945 status=MagickFalse;
cristy1ca3eb32009-10-15 18:41:54 +0000946 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000947 {
948 magic_list=NewLinkedList(0);
949 if (magic_list == (LinkedListInfo *) NULL)
950 {
951 ThrowFileException(exception,ResourceLimitError,
952 "MemoryAllocationFailed",filename);
953 return(MagickFalse);
954 }
955 }
cristybb503372010-05-27 20:51:26 +0000956 for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
cristy1ca3eb32009-10-15 18:41:54 +0000957 {
958 MagicInfo
959 *magic_info;
960
cristy54a531d2009-10-21 17:58:01 +0000961 register const MagicMapInfo
962 *p;
963
964 p=MagicMap+i;
cristy73bd4a52010-10-05 11:24:23 +0000965 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
cristy1ca3eb32009-10-15 18:41:54 +0000966 if (magic_info == (MagicInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000967 {
968 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000969 ResourceLimitError,"MemoryAllocationFailed","'%s'",magic_info->name);
cristye3e77a12009-10-16 00:47:21 +0000970 continue;
971 }
cristy1ca3eb32009-10-15 18:41:54 +0000972 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
cristy38b8ed92009-10-16 01:20:21 +0000973 magic_info->path=(char *) "[built-in]";
cristy1ca3eb32009-10-15 18:41:54 +0000974 magic_info->name=(char *) p->name;
975 magic_info->offset=p->offset;
976 magic_info->target=(char *) p->magic;
cristye3e77a12009-10-16 00:47:21 +0000977 magic_info->magic=(unsigned char *) p->magic;
cristy1ca3eb32009-10-15 18:41:54 +0000978 magic_info->length=p->length;
979 magic_info->exempt=MagickTrue;
980 magic_info->signature=MagickSignature;
981 status=AppendValueToLinkedList(magic_list,magic_info);
982 if (status == MagickFalse)
983 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000984 ResourceLimitError,"MemoryAllocationFailed","'%s'",magic_info->name);
cristy1ca3eb32009-10-15 18:41:54 +0000985 }
986 /*
987 Load external magic map.
988 */
cristy3ed852e2009-09-05 21:47:34 +0000989 *path='\0';
990 options=GetConfigureOptions(filename,exception);
991 option=(const StringInfo *) GetNextValueInLinkedList(options);
992 while (option != (const StringInfo *) NULL)
993 {
994 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
995 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
996 GetStringInfoPath(option),0,exception);
997 option=(const StringInfo *) GetNextValueInLinkedList(options);
998 }
999 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +00001000 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001001}
cristyf34a1452009-10-24 22:29:27 +00001002
1003/*
1004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005% %
1006% %
1007% %
1008+ M a g i c C o m p o n e n t G e n e s i s %
1009% %
1010% %
1011% %
1012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1013%
1014% MagicComponentGenesis() instantiates the magic component.
1015%
1016% The format of the MagicComponentGenesis method is:
1017%
1018% MagickBooleanType MagicComponentGenesis(void)
1019%
1020*/
cristy5ff4eaf2011-09-03 01:38:02 +00001021MagickPrivate MagickBooleanType MagicComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +00001022{
cristy165b6092009-10-26 13:52:10 +00001023 AcquireSemaphoreInfo(&magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001024 return(MagickTrue);
1025}
1026
1027/*
1028%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029% %
1030% %
1031% %
1032+ M a g i c C o m p o n e n t T e r m i n u s %
1033% %
1034% %
1035% %
1036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037%
1038% MagicComponentTerminus() destroys the magic component.
1039%
1040% The format of the MagicComponentTerminus method is:
1041%
1042% MagicComponentTerminus(void)
1043%
1044*/
1045
1046static void *DestroyMagicElement(void *magic_info)
1047{
1048 register MagicInfo
1049 *p;
1050
1051 p=(MagicInfo *) magic_info;
1052 if (p->exempt == MagickFalse)
1053 {
1054 if (p->path != (char *) NULL)
1055 p->path=DestroyString(p->path);
1056 if (p->name != (char *) NULL)
1057 p->name=DestroyString(p->name);
1058 if (p->target != (char *) NULL)
1059 p->target=DestroyString(p->target);
1060 if (p->magic != (unsigned char *) NULL)
1061 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1062 }
1063 p=(MagicInfo *) RelinquishMagickMemory(p);
1064 return((void *) NULL);
1065}
1066
cristy5ff4eaf2011-09-03 01:38:02 +00001067MagickPrivate void MagicComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001068{
cristy18b17442009-10-25 18:36:48 +00001069 if (magic_semaphore == (SemaphoreInfo *) NULL)
1070 AcquireSemaphoreInfo(&magic_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001071 LockSemaphoreInfo(magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001072 if (magic_list != (LinkedListInfo *) NULL)
1073 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
1074 instantiate_magic=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001075 UnlockSemaphoreInfo(magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001076 DestroySemaphoreInfo(&magic_semaphore);
1077}