1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                         BBBB   L       OOO   BBBB                           %
7 %                         B   B  L      O   O  B   B                          %
8 %                         BBBB   L      O   O  BBBB                           %
9 %                         B   B  L      O   O  B   B                          %
10 %                         BBBB   LLLLL   OOO   BBBB                           %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Binary Large OBjectS Methods                 %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1999                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2019 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 /*
41   Include declarations.
42 */
43 #ifdef __VMS
44 #include  <types.h>
45 #include  <mman.h>
46 #endif
47 #include "MagickCore/studio.h"
48 #include "MagickCore/blob.h"
49 #include "MagickCore/blob-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image-private.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/locale_.h"
60 #include "MagickCore/log.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/memory-private.h"
64 #include "MagickCore/nt-base-private.h"
65 #include "MagickCore/option.h"
66 #include "MagickCore/policy.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/semaphore.h"
69 #include "MagickCore/string_.h"
70 #include "MagickCore/string-private.h"
71 #include "MagickCore/token.h"
72 #include "MagickCore/utility.h"
73 #include "MagickCore/utility-private.h"
74 #if defined(MAGICKCORE_ZLIB_DELEGATE)
75 #include "zlib.h"
76 #endif
77 #if defined(MAGICKCORE_BZLIB_DELEGATE)
78 #include "bzlib.h"
79 #endif
80 
81 /*
82   Define declarations.
83 */
84 #define MagickMaxBlobExtent  (8*8192)
85 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
86 # define MAP_ANONYMOUS  MAP_ANON
87 #endif
88 #if !defined(MAP_FAILED)
89 #define MAP_FAILED  ((void *) -1)
90 #endif
91 #if defined(__OS2__)
92 #include <io.h>
93 #define _O_BINARY O_BINARY
94 #endif
95 
96 /*
97   Typedef declarations.
98 */
99 typedef union FileInfo
100 {
101   FILE
102     *file;
103 
104 #if defined(MAGICKCORE_ZLIB_DELEGATE)
105   gzFile
106     gzfile;
107 #endif
108 
109 #if defined(MAGICKCORE_BZLIB_DELEGATE)
110   BZFILE
111     *bzfile;
112 #endif
113 } FileInfo;
114 
115 struct _BlobInfo
116 {
117   size_t
118     length,
119     extent,
120     quantum;
121 
122   BlobMode
123     mode;
124 
125   MagickBooleanType
126     mapped,
127     eof;
128 
129   int
130     error;
131 
132   MagickOffsetType
133     offset;
134 
135   MagickSizeType
136     size;
137 
138   MagickBooleanType
139     exempt,
140     synchronize,
141     status,
142     temporary;
143 
144   StreamType
145     type;
146 
147   FileInfo
148     file_info;
149 
150   struct stat
151     properties;
152 
153   StreamHandler
154     stream;
155 
156   CustomStreamInfo
157     *custom_stream;
158 
159   unsigned char
160     *data;
161 
162   MagickBooleanType
163     debug;
164 
165   SemaphoreInfo
166     *semaphore;
167 
168   ssize_t
169     reference_count;
170 
171   size_t
172     signature;
173 };
174 
175 struct _CustomStreamInfo
176 {
177   CustomStreamHandler
178     reader,
179     writer;
180 
181   CustomStreamSeeker
182     seeker;
183 
184   CustomStreamTeller
185     teller;
186 
187   void
188     *data;
189 
190   size_t
191     signature;
192 };
193 
194 /*
195   Forward declarations.
196 */
197 static int
198   SyncBlob(Image *);
199 
200 /*
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202 %                                                                             %
203 %                                                                             %
204 %                                                                             %
205 +   A c q u i r e C u s t o m S t r e a m I n f o                             %
206 %                                                                             %
207 %                                                                             %
208 %                                                                             %
209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 %
211 %  AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
212 %
213 %  The format of the AcquireCustomStreamInfo method is:
214 %
215 %      CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
216 %
217 %  A description of each parameter follows:
218 %
219 %    o exception: return any errors or warnings in this structure.
220 %
221 */
AcquireCustomStreamInfo(ExceptionInfo * magick_unused (exception))222 MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
223   ExceptionInfo *magick_unused(exception))
224 {
225   CustomStreamInfo
226     *custom_stream;
227 
228   magick_unreferenced(exception);
229   custom_stream=(CustomStreamInfo *) AcquireCriticalMemory(
230     sizeof(*custom_stream));
231   (void) memset(custom_stream,0,sizeof(*custom_stream));
232   custom_stream->signature=MagickCoreSignature;
233   return(custom_stream);
234 }
235 
236 /*
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 %                                                                             %
239 %                                                                             %
240 %                                                                             %
241 +   A t t a c h B l o b                                                       %
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %
247 %  AttachBlob() attaches a blob to the BlobInfo structure.
248 %
249 %  The format of the AttachBlob method is:
250 %
251 %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
252 %
253 %  A description of each parameter follows:
254 %
255 %    o blob_info: Specifies a pointer to a BlobInfo structure.
256 %
257 %    o blob: the address of a character stream in one of the image formats
258 %      understood by ImageMagick.
259 %
260 %    o length: This size_t integer reflects the length in bytes of the blob.
261 %
262 */
AttachBlob(BlobInfo * blob_info,const void * blob,const size_t length)263 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
264   const size_t length)
265 {
266   assert(blob_info != (BlobInfo *) NULL);
267   if (blob_info->debug != MagickFalse)
268     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
269   blob_info->length=length;
270   blob_info->extent=length;
271   blob_info->quantum=(size_t) MagickMaxBlobExtent;
272   blob_info->offset=0;
273   blob_info->type=BlobStream;
274   blob_info->file_info.file=(FILE *) NULL;
275   blob_info->data=(unsigned char *) blob;
276   blob_info->mapped=MagickFalse;
277 }
278 
279 /*
280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281 %                                                                             %
282 %                                                                             %
283 %                                                                             %
284 +   A t t a c h C u s t o m S t r e a m                                       %
285 %                                                                             %
286 %                                                                             %
287 %                                                                             %
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 %
290 %  AttachCustomStream() attaches a CustomStreamInfo to the BlobInfo structure.
291 %
292 %  The format of the AttachCustomStream method is:
293 %
294 %      void AttachCustomStream(BlobInfo *blob_info,
295 %        CustomStreamInfo *custom_stream)
296 %
297 %  A description of each parameter follows:
298 %
299 %    o blob_info: specifies a pointer to a BlobInfo structure.
300 %
301 %    o custom_stream: the custom stream info.
302 %
303 */
AttachCustomStream(BlobInfo * blob_info,CustomStreamInfo * custom_stream)304 MagickExport void AttachCustomStream(BlobInfo *blob_info,
305   CustomStreamInfo *custom_stream)
306 {
307   assert(blob_info != (BlobInfo *) NULL);
308   assert(custom_stream != (CustomStreamInfo *) NULL);
309   assert(custom_stream->signature == MagickCoreSignature);
310   if (blob_info->debug != MagickFalse)
311     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
312   blob_info->type=CustomStream;
313   blob_info->custom_stream=custom_stream;
314 }
315 
316 /*
317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 %                                                                             %
319 %                                                                             %
320 %                                                                             %
321 +   B l o b T o F i l e                                                       %
322 %                                                                             %
323 %                                                                             %
324 %                                                                             %
325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 %
327 %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
328 %  occurs otherwise MagickTrue.
329 %
330 %  The format of the BlobToFile method is:
331 %
332 %       MagickBooleanType BlobToFile(char *filename,const void *blob,
333 %         const size_t length,ExceptionInfo *exception)
334 %
335 %  A description of each parameter follows:
336 %
337 %    o filename: Write the blob to this file.
338 %
339 %    o blob: the address of a blob.
340 %
341 %    o length: This length in bytes of the blob.
342 %
343 %    o exception: return any errors or warnings in this structure.
344 %
345 */
BlobToFile(char * filename,const void * blob,const size_t length,ExceptionInfo * exception)346 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
347   const size_t length,ExceptionInfo *exception)
348 {
349   int
350     file;
351 
352   register size_t
353     i;
354 
355   ssize_t
356     count;
357 
358   assert(filename != (const char *) NULL);
359   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
360   assert(blob != (const void *) NULL);
361   if (*filename == '\0')
362     file=AcquireUniqueFileResource(filename);
363   else
364     file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
365   if (file == -1)
366     {
367       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
368       return(MagickFalse);
369     }
370   for (i=0; i < length; i+=count)
371   {
372     count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
373       SSIZE_MAX));
374     if (count <= 0)
375       {
376         count=0;
377         if (errno != EINTR)
378           break;
379       }
380   }
381   file=close(file);
382   if ((file == -1) || (i < length))
383     {
384       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
385       return(MagickFalse);
386     }
387   return(MagickTrue);
388 }
389 
390 /*
391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392 %                                                                             %
393 %                                                                             %
394 %                                                                             %
395 %   B l o b T o I m a g e                                                     %
396 %                                                                             %
397 %                                                                             %
398 %                                                                             %
399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 %
401 %  BlobToImage() implements direct to memory image formats.  It returns the
402 %  blob as an image.
403 %
404 %  The format of the BlobToImage method is:
405 %
406 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
407 %        const size_t length,ExceptionInfo *exception)
408 %
409 %  A description of each parameter follows:
410 %
411 %    o image_info: the image info.
412 %
413 %    o blob: the address of a character stream in one of the image formats
414 %      understood by ImageMagick.
415 %
416 %    o length: This size_t integer reflects the length in bytes of the blob.
417 %
418 %    o exception: return any errors or warnings in this structure.
419 %
420 */
BlobToImage(const ImageInfo * image_info,const void * blob,const size_t length,ExceptionInfo * exception)421 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
422   const size_t length,ExceptionInfo *exception)
423 {
424   const MagickInfo
425     *magick_info;
426 
427   Image
428     *image;
429 
430   ImageInfo
431     *blob_info,
432     *clone_info;
433 
434   MagickBooleanType
435     status;
436 
437   assert(image_info != (ImageInfo *) NULL);
438   assert(image_info->signature == MagickCoreSignature);
439   if (image_info->debug != MagickFalse)
440     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
441       image_info->filename);
442   assert(exception != (ExceptionInfo *) NULL);
443   if ((blob == (const void *) NULL) || (length == 0))
444     {
445       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
446         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
447       return((Image *) NULL);
448     }
449   blob_info=CloneImageInfo(image_info);
450   blob_info->blob=(void *) blob;
451   blob_info->length=length;
452   if (*blob_info->magick == '\0')
453     (void) SetImageInfo(blob_info,0,exception);
454   magick_info=GetMagickInfo(blob_info->magick,exception);
455   if (magick_info == (const MagickInfo *) NULL)
456     {
457       (void) ThrowMagickException(exception,GetMagickModule(),
458         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
459         blob_info->magick);
460       blob_info=DestroyImageInfo(blob_info);
461       return((Image *) NULL);
462     }
463   if (GetMagickBlobSupport(magick_info) != MagickFalse)
464     {
465       char
466         filename[MagickPathExtent];
467 
468       /*
469         Native blob support for this image format.
470       */
471       (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
472       (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
473         blob_info->magick,filename);
474       image=ReadImage(blob_info,exception);
475       if (image != (Image *) NULL)
476         (void) DetachBlob(image->blob);
477       blob_info=DestroyImageInfo(blob_info);
478       return(image);
479     }
480   /*
481     Write blob to a temporary file on disk.
482   */
483   blob_info->blob=(void *) NULL;
484   blob_info->length=0;
485   *blob_info->filename='\0';
486   status=BlobToFile(blob_info->filename,blob,length,exception);
487   if (status == MagickFalse)
488     {
489       (void) RelinquishUniqueFileResource(blob_info->filename);
490       blob_info=DestroyImageInfo(blob_info);
491       return((Image *) NULL);
492     }
493   clone_info=CloneImageInfo(blob_info);
494   (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
495     blob_info->magick,blob_info->filename);
496   image=ReadImage(clone_info,exception);
497   if (image != (Image *) NULL)
498     {
499       Image
500         *images;
501 
502       /*
503         Restore original filenames and image format.
504       */
505       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
506       {
507         (void) CopyMagickString(images->filename,image_info->filename,
508           MagickPathExtent);
509         (void) CopyMagickString(images->magick_filename,image_info->filename,
510           MagickPathExtent);
511         (void) CopyMagickString(images->magick,magick_info->name,
512           MagickPathExtent);
513         images=GetNextImageInList(images);
514       }
515     }
516   clone_info=DestroyImageInfo(clone_info);
517   (void) RelinquishUniqueFileResource(blob_info->filename);
518   blob_info=DestroyImageInfo(blob_info);
519   return(image);
520 }
521 
522 /*
523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524 %                                                                             %
525 %                                                                             %
526 %                                                                             %
527 +   C l o n e B l o b I n f o                                                 %
528 %                                                                             %
529 %                                                                             %
530 %                                                                             %
531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532 %
533 %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
534 %  blob info is NULL, a new one.
535 %
536 %  The format of the CloneBlobInfo method is:
537 %
538 %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
539 %
540 %  A description of each parameter follows:
541 %
542 %    o blob_info: the blob info.
543 %
544 */
CloneBlobInfo(const BlobInfo * blob_info)545 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
546 {
547   BlobInfo
548     *clone_info;
549 
550   SemaphoreInfo
551     *semaphore;
552 
553   clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
554   GetBlobInfo(clone_info);
555   if (blob_info == (BlobInfo *) NULL)
556     return(clone_info);
557   semaphore=clone_info->semaphore;
558   (void) memcpy(clone_info,blob_info,sizeof(*clone_info));
559   if (blob_info->mapped != MagickFalse)
560     (void) AcquireMagickResource(MapResource,blob_info->length);
561   clone_info->semaphore=semaphore;
562   LockSemaphoreInfo(clone_info->semaphore);
563   clone_info->reference_count=1;
564   UnlockSemaphoreInfo(clone_info->semaphore);
565   return(clone_info);
566 }
567 
568 /*
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %                                                                             %
571 %                                                                             %
572 %                                                                             %
573 +   C l o s e B l o b                                                         %
574 %                                                                             %
575 %                                                                             %
576 %                                                                             %
577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578 %
579 %  CloseBlob() closes a stream associated with the image.
580 %
581 %  The format of the CloseBlob method is:
582 %
583 %      MagickBooleanType CloseBlob(Image *image)
584 %
585 %  A description of each parameter follows:
586 %
587 %    o image: the image.
588 %
589 */
CloseBlob(Image * image)590 MagickExport MagickBooleanType CloseBlob(Image *image)
591 {
592   BlobInfo
593     *magick_restrict blob_info;
594 
595   int
596     status;
597 
598   /*
599     Close image file.
600   */
601   assert(image != (Image *) NULL);
602   assert(image->signature == MagickCoreSignature);
603   if (image->debug != MagickFalse)
604     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
605   blob_info=image->blob;
606   if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
607     return(MagickTrue);
608   status=SyncBlob(image);
609   switch (blob_info->type)
610   {
611     case UndefinedStream:
612     case StandardStream:
613       break;
614     case FileStream:
615     case PipeStream:
616     {
617       if (blob_info->synchronize != MagickFalse)
618         status=fsync(fileno(blob_info->file_info.file));
619       status=ferror(blob_info->file_info.file);
620       break;
621     }
622     case ZipStream:
623     {
624 #if defined(MAGICKCORE_ZLIB_DELEGATE)
625       (void) gzerror(blob_info->file_info.gzfile,&status);
626 #endif
627       break;
628     }
629     case BZipStream:
630     {
631 #if defined(MAGICKCORE_BZLIB_DELEGATE)
632       (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
633 #endif
634       break;
635     }
636     case FifoStream:
637       break;
638     case BlobStream:
639     {
640       if (blob_info->file_info.file != (FILE *) NULL)
641         {
642           if (blob_info->synchronize != MagickFalse)
643             status=fsync(fileno(blob_info->file_info.file));
644           status=ferror(blob_info->file_info.file);
645         }
646       break;
647     }
648     case CustomStream:
649       break;
650   }
651   blob_info->status=status < 0 ? MagickTrue : MagickFalse;
652   blob_info->size=GetBlobSize(image);
653   image->extent=blob_info->size;
654   blob_info->eof=MagickFalse;
655   blob_info->error=0;
656   blob_info->mode=UndefinedBlobMode;
657   if (blob_info->exempt != MagickFalse)
658     {
659       blob_info->type=UndefinedStream;
660       return(blob_info->status);
661     }
662   switch (blob_info->type)
663   {
664     case UndefinedStream:
665     case StandardStream:
666       break;
667     case FileStream:
668     {
669       status=fclose(blob_info->file_info.file);
670       break;
671     }
672     case PipeStream:
673     {
674 #if defined(MAGICKCORE_HAVE_PCLOSE)
675       status=pclose(blob_info->file_info.file);
676 #endif
677       break;
678     }
679     case ZipStream:
680     {
681 #if defined(MAGICKCORE_ZLIB_DELEGATE)
682       status=gzclose(blob_info->file_info.gzfile);
683 #endif
684       break;
685     }
686     case BZipStream:
687     {
688 #if defined(MAGICKCORE_BZLIB_DELEGATE)
689       BZ2_bzclose(blob_info->file_info.bzfile);
690 #endif
691       break;
692     }
693     case FifoStream:
694       break;
695     case BlobStream:
696     {
697       if (blob_info->file_info.file != (FILE *) NULL)
698         status=fclose(blob_info->file_info.file);
699       break;
700     }
701     case CustomStream:
702       break;
703   }
704   (void) DetachBlob(blob_info);
705   blob_info->status=status < 0 ? MagickTrue : MagickFalse;
706   return(blob_info->status);
707 }
708 
709 /*
710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
711 %                                                                             %
712 %                                                                             %
713 %                                                                             %
714 %   C u s t o m S t r e a m T o I m a g e                                     %
715 %                                                                             %
716 %                                                                             %
717 %                                                                             %
718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719 %
720 %  CustomStreamToImage() is the equivalent of ReadImage(), but reads the
721 %  formatted "file" from the suplied method rather than to an actual file.
722 %
723 %  The format of the CustomStreamToImage method is:
724 %
725 %      Image *CustomStreamToImage(const ImageInfo *image_info,
726 %         ExceptionInfo *exception)
727 %
728 %  A description of each parameter follows:
729 %
730 %    o image_info: the image info.
731 %
732 %    o exception: return any errors or warnings in this structure.
733 %
734 */
CustomStreamToImage(const ImageInfo * image_info,ExceptionInfo * exception)735 MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
736   ExceptionInfo *exception)
737 {
738   const MagickInfo
739     *magick_info;
740 
741   Image
742     *image;
743 
744   ImageInfo
745     *blob_info;
746 
747   assert(image_info != (ImageInfo *) NULL);
748   assert(image_info->signature == MagickCoreSignature);
749   if (image_info->debug != MagickFalse)
750     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
751       image_info->filename);
752   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
753   assert(image_info->custom_stream->signature == MagickCoreSignature);
754   assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
755   assert(exception != (ExceptionInfo *) NULL);
756   blob_info=CloneImageInfo(image_info);
757   if (*blob_info->magick == '\0')
758     (void) SetImageInfo(blob_info,0,exception);
759   magick_info=GetMagickInfo(blob_info->magick,exception);
760   if (magick_info == (const MagickInfo *) NULL)
761     {
762       (void) ThrowMagickException(exception,GetMagickModule(),
763         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
764         blob_info->magick);
765       blob_info=DestroyImageInfo(blob_info);
766       return((Image *) NULL);
767     }
768   image=(Image *) NULL;
769   if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
770       (*blob_info->filename != '\0'))
771     {
772       char
773         filename[MagickPathExtent];
774 
775       /*
776         Native blob support for this image format or SetImageInfo changed the
777         blob to a file.
778       */
779       (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
780       (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
781         blob_info->magick,filename);
782       image=ReadImage(blob_info,exception);
783       if (image != (Image *) NULL)
784         (void) CloseBlob(image);
785     }
786   else
787     {
788       char
789         unique[MagickPathExtent];
790 
791       int
792         file;
793 
794       ImageInfo
795         *clone_info;
796 
797       unsigned char
798         *blob;
799 
800       /*
801         Write data to file on disk.
802       */
803       blob_info->custom_stream=(CustomStreamInfo *) NULL;
804       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
805         sizeof(*blob));
806       if (blob == (unsigned char *) NULL)
807         {
808           ThrowFileException(exception,BlobError,"UnableToReadBlob",
809             image_info->filename);
810           blob_info=DestroyImageInfo(blob_info);
811           return((Image *) NULL);
812         }
813       file=AcquireUniqueFileResource(unique);
814       if (file == -1)
815         {
816           ThrowFileException(exception,BlobError,"UnableToReadBlob",
817             image_info->filename);
818           blob=(unsigned char *) RelinquishMagickMemory(blob);
819           blob_info=DestroyImageInfo(blob_info);
820           return((Image *) NULL);
821         }
822       clone_info=CloneImageInfo(blob_info);
823       blob_info->file=fdopen(file,"wb+");
824       if (blob_info->file != (FILE *) NULL)
825         {
826           ssize_t
827             count;
828 
829           count=(ssize_t) MagickMaxBufferExtent;
830           while (count == (ssize_t) MagickMaxBufferExtent)
831           {
832             count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
833               image_info->custom_stream->data);
834             count=(ssize_t) write(file,(const char *) blob,(size_t) count);
835           }
836           (void) fclose(blob_info->file);
837           (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
838             "%s:%s",blob_info->magick,unique);
839           image=ReadImage(clone_info,exception);
840           if (image != (Image *) NULL)
841             {
842               Image
843                 *images;
844 
845               /*
846                 Restore original filenames and image format.
847               */
848               for (images=GetFirstImageInList(image); images != (Image *) NULL; )
849               {
850                 (void) CopyMagickString(images->filename,image_info->filename,
851                   MagickPathExtent);
852                 (void) CopyMagickString(images->magick_filename,
853                   image_info->filename,MagickPathExtent);
854                 (void) CopyMagickString(images->magick,magick_info->name,
855                   MagickPathExtent);
856                 (void) CloseBlob(images);
857                 images=GetNextImageInList(images);
858               }
859             }
860         }
861       clone_info=DestroyImageInfo(clone_info);
862       blob=(unsigned char *) RelinquishMagickMemory(blob);
863       (void) RelinquishUniqueFileResource(unique);
864     }
865   blob_info=DestroyImageInfo(blob_info);
866   return(image);
867 }
868 
869 /*
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 %                                                                             %
872 %                                                                             %
873 %                                                                             %
874 +   D e s t r o y B l o b                                                     %
875 %                                                                             %
876 %                                                                             %
877 %                                                                             %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879 %
880 %  DestroyBlob() deallocates memory associated with a blob.
881 %
882 %  The format of the DestroyBlob method is:
883 %
884 %      void DestroyBlob(Image *image)
885 %
886 %  A description of each parameter follows:
887 %
888 %    o image: the image.
889 %
890 */
DestroyBlob(Image * image)891 MagickExport void DestroyBlob(Image *image)
892 {
893   BlobInfo
894     *magick_restrict blob_info;
895 
896   MagickBooleanType
897     destroy;
898 
899   assert(image != (Image *) NULL);
900   assert(image->signature == MagickCoreSignature);
901   if (image->debug != MagickFalse)
902     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
903   assert(image->blob != (BlobInfo *) NULL);
904   assert(image->blob->signature == MagickCoreSignature);
905   blob_info=image->blob;
906   destroy=MagickFalse;
907   LockSemaphoreInfo(blob_info->semaphore);
908   blob_info->reference_count--;
909   assert(blob_info->reference_count >= 0);
910   if (blob_info->reference_count == 0)
911     destroy=MagickTrue;
912   UnlockSemaphoreInfo(blob_info->semaphore);
913   if (destroy == MagickFalse)
914     {
915       image->blob=(BlobInfo *) NULL;
916       return;
917     }
918   (void) CloseBlob(image);
919   if (blob_info->mapped != MagickFalse)
920     {
921       (void) UnmapBlob(blob_info->data,blob_info->length);
922       RelinquishMagickResource(MapResource,blob_info->length);
923     }
924   if (blob_info->semaphore != (SemaphoreInfo *) NULL)
925     RelinquishSemaphoreInfo(&blob_info->semaphore);
926   blob_info->signature=(~MagickCoreSignature);
927   image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
928 }
929 
930 /*
931 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
932 %                                                                             %
933 %                                                                             %
934 %                                                                             %
935 +   D e s t r o y C u s t o m S t r e a m I n f o                             %
936 %                                                                             %
937 %                                                                             %
938 %                                                                             %
939 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940 %
941 %  DestroyCustomStreamInfo() destroys memory associated with the
942 %  CustomStreamInfo structure.
943 %
944 %  The format of the DestroyCustomStreamInfo method is:
945 %
946 %      CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
947 %
948 %  A description of each parameter follows:
949 %
950 %    o custom_stream: the custom stream info.
951 %
952 */
DestroyCustomStreamInfo(CustomStreamInfo * custom_stream)953 MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
954   CustomStreamInfo *custom_stream)
955 {
956   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
957   assert(custom_stream != (CustomStreamInfo *) NULL);
958   assert(custom_stream->signature == MagickCoreSignature);
959   custom_stream->signature=(~MagickCoreSignature);
960   custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
961   return(custom_stream);
962 }
963 
964 /*
965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966 %                                                                             %
967 %                                                                             %
968 %                                                                             %
969 +   D e t a c h B l o b                                                       %
970 %                                                                             %
971 %                                                                             %
972 %                                                                             %
973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974 %
975 %  DetachBlob() detaches a blob from the BlobInfo structure.
976 %
977 %  The format of the DetachBlob method is:
978 %
979 %      void *DetachBlob(BlobInfo *blob_info)
980 %
981 %  A description of each parameter follows:
982 %
983 %    o blob_info: Specifies a pointer to a BlobInfo structure.
984 %
985 */
DetachBlob(BlobInfo * blob_info)986 MagickExport void *DetachBlob(BlobInfo *blob_info)
987 {
988   void
989     *data;
990 
991   assert(blob_info != (BlobInfo *) NULL);
992   if (blob_info->debug != MagickFalse)
993     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
994   if (blob_info->mapped != MagickFalse)
995     {
996       (void) UnmapBlob(blob_info->data,blob_info->length);
997       RelinquishMagickResource(MapResource,blob_info->length);
998     }
999   blob_info->mapped=MagickFalse;
1000   blob_info->length=0;
1001   blob_info->offset=0;
1002   blob_info->eof=MagickFalse;
1003   blob_info->error=0;
1004   blob_info->exempt=MagickFalse;
1005   blob_info->type=UndefinedStream;
1006   blob_info->file_info.file=(FILE *) NULL;
1007   data=blob_info->data;
1008   blob_info->data=(unsigned char *) NULL;
1009   blob_info->stream=(StreamHandler) NULL;
1010   blob_info->custom_stream=(CustomStreamInfo *) NULL;
1011   return(data);
1012 }
1013 
1014 /*
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016 %                                                                             %
1017 %                                                                             %
1018 %                                                                             %
1019 +   D i s a s s o c i a t e B l o b                                           %
1020 %                                                                             %
1021 %                                                                             %
1022 %                                                                             %
1023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024 %
1025 %  DisassociateBlob() disassociates the image stream.  It checks if the
1026 %  blob of the specified image is referenced by other images. If the reference
1027 %  count is higher then 1 a new blob is assigned to the specified image.
1028 %
1029 %  The format of the DisassociateBlob method is:
1030 %
1031 %      void DisassociateBlob(const Image *image)
1032 %
1033 %  A description of each parameter follows:
1034 %
1035 %    o image: the image.
1036 %
1037 */
DisassociateBlob(Image * image)1038 MagickExport void DisassociateBlob(Image *image)
1039 {
1040   BlobInfo
1041     *magick_restrict blob_info,
1042     *clone_info;
1043 
1044   MagickBooleanType
1045     clone;
1046 
1047   assert(image != (Image *) NULL);
1048   assert(image->signature == MagickCoreSignature);
1049   if (image->debug != MagickFalse)
1050     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1051   assert(image->blob != (BlobInfo *) NULL);
1052   assert(image->blob->signature == MagickCoreSignature);
1053   blob_info=image->blob;
1054   clone=MagickFalse;
1055   LockSemaphoreInfo(blob_info->semaphore);
1056   assert(blob_info->reference_count >= 0);
1057   if (blob_info->reference_count > 1)
1058     clone=MagickTrue;
1059   UnlockSemaphoreInfo(blob_info->semaphore);
1060   if (clone == MagickFalse)
1061     return;
1062   clone_info=CloneBlobInfo(blob_info);
1063   DestroyBlob(image);
1064   image->blob=clone_info;
1065 }
1066 
1067 /*
1068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069 %                                                                             %
1070 %                                                                             %
1071 %                                                                             %
1072 +  D i s c a r d B l o b B y t e s                                            %
1073 %                                                                             %
1074 %                                                                             %
1075 %                                                                             %
1076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1077 %
1078 %  DiscardBlobBytes() discards bytes in a blob.
1079 %
1080 %  The format of the DiscardBlobBytes method is:
1081 %
1082 %      MagickBooleanType DiscardBlobBytes(Image *image,
1083 %        const MagickSizeType length)
1084 %
1085 %  A description of each parameter follows.
1086 %
1087 %    o image: the image.
1088 %
1089 %    o length:  the number of bytes to skip.
1090 %
1091 */
DiscardBlobBytes(Image * image,const MagickSizeType length)1092 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
1093   const MagickSizeType length)
1094 {
1095   register MagickOffsetType
1096     i;
1097 
1098   size_t
1099     quantum;
1100 
1101   ssize_t
1102     count;
1103 
1104   unsigned char
1105     buffer[16384];
1106 
1107   assert(image != (Image *) NULL);
1108   assert(image->signature == MagickCoreSignature);
1109   if (length != (MagickSizeType) ((MagickOffsetType) length))
1110     return(MagickFalse);
1111   count=0;
1112   for (i=0; i < (MagickOffsetType) length; i+=count)
1113   {
1114     quantum=(size_t) MagickMin(length-i,sizeof(buffer));
1115     (void) ReadBlobStream(image,quantum,buffer,&count);
1116     if (count <= 0)
1117       {
1118         count=0;
1119         if (errno != EINTR)
1120           break;
1121       }
1122   }
1123   return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
1124 }
1125 
1126 /*
1127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1128 %                                                                             %
1129 %                                                                             %
1130 %                                                                             %
1131 +   D u p l i c a t e s B l o b                                               %
1132 %                                                                             %
1133 %                                                                             %
1134 %                                                                             %
1135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1136 %
1137 %  DuplicateBlob() duplicates a blob descriptor.
1138 %
1139 %  The format of the DuplicateBlob method is:
1140 %
1141 %      void DuplicateBlob(Image *image,const Image *duplicate)
1142 %
1143 %  A description of each parameter follows:
1144 %
1145 %    o image: the image.
1146 %
1147 %    o duplicate: the duplicate image.
1148 %
1149 */
DuplicateBlob(Image * image,const Image * duplicate)1150 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
1151 {
1152   assert(image != (Image *) NULL);
1153   assert(image->signature == MagickCoreSignature);
1154   if (image->debug != MagickFalse)
1155     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1156   assert(duplicate != (Image *) NULL);
1157   assert(duplicate->signature == MagickCoreSignature);
1158   DestroyBlob(image);
1159   image->blob=ReferenceBlob(duplicate->blob);
1160 }
1161 
1162 /*
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 %                                                                             %
1165 %                                                                             %
1166 %                                                                             %
1167 +  E O F B l o b                                                              %
1168 %                                                                             %
1169 %                                                                             %
1170 %                                                                             %
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172 %
1173 %  EOFBlob() returns a non-zero value when EOF has been detected reading from
1174 %  a blob or file.
1175 %
1176 %  The format of the EOFBlob method is:
1177 %
1178 %      int EOFBlob(const Image *image)
1179 %
1180 %  A description of each parameter follows:
1181 %
1182 %    o image: the image.
1183 %
1184 */
EOFBlob(const Image * image)1185 MagickExport int EOFBlob(const Image *image)
1186 {
1187   BlobInfo
1188     *magick_restrict blob_info;
1189 
1190   assert(image != (Image *) NULL);
1191   assert(image->signature == MagickCoreSignature);
1192   if (image->debug != MagickFalse)
1193     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1194   assert(image->blob != (BlobInfo *) NULL);
1195   assert(image->blob->type != UndefinedStream);
1196   blob_info=image->blob;
1197   switch (blob_info->type)
1198   {
1199     case UndefinedStream:
1200     case StandardStream:
1201       break;
1202     case FileStream:
1203     case PipeStream:
1204     {
1205       blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
1206         MagickFalse;
1207       break;
1208     }
1209     case ZipStream:
1210     {
1211 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1212       blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
1213         MagickFalse;
1214 #endif
1215       break;
1216     }
1217     case BZipStream:
1218     {
1219 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1220       int
1221         status;
1222 
1223       status=0;
1224       (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
1225       blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
1226 #endif
1227       break;
1228     }
1229     case FifoStream:
1230     {
1231       blob_info->eof=MagickFalse;
1232       break;
1233     }
1234     case BlobStream:
1235       break;
1236     case CustomStream:
1237       break;
1238   }
1239   return((int) blob_info->eof);
1240 }
1241 
1242 /*
1243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1244 %                                                                             %
1245 %                                                                             %
1246 %                                                                             %
1247 +  E r r o r B l o b                                                          %
1248 %                                                                             %
1249 %                                                                             %
1250 %                                                                             %
1251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252 %
1253 %  ErrorBlob() returns a non-zero value when an error has been detected reading
1254 %  from a blob or file.
1255 %
1256 %  The format of the ErrorBlob method is:
1257 %
1258 %      int ErrorBlob(const Image *image)
1259 %
1260 %  A description of each parameter follows:
1261 %
1262 %    o image: the image.
1263 %
1264 */
ErrorBlob(const Image * image)1265 MagickExport int ErrorBlob(const Image *image)
1266 {
1267   BlobInfo
1268     *magick_restrict blob_info;
1269 
1270   assert(image != (Image *) NULL);
1271   assert(image->signature == MagickCoreSignature);
1272   if (image->debug != MagickFalse)
1273     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1274   assert(image->blob != (BlobInfo *) NULL);
1275   assert(image->blob->type != UndefinedStream);
1276   blob_info=image->blob;
1277   switch (blob_info->type)
1278   {
1279     case UndefinedStream:
1280     case StandardStream:
1281       break;
1282     case FileStream:
1283     case PipeStream:
1284     {
1285       blob_info->error=ferror(blob_info->file_info.file);
1286       break;
1287     }
1288     case ZipStream:
1289     {
1290 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1291       (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1292 #endif
1293       break;
1294     }
1295     case BZipStream:
1296     {
1297 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1298       (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1299 #endif
1300       break;
1301     }
1302     case FifoStream:
1303     {
1304       blob_info->error=0;
1305       break;
1306     }
1307     case BlobStream:
1308       break;
1309     case CustomStream:
1310       break;
1311   }
1312   return(blob_info->error);
1313 }
1314 
1315 /*
1316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1317 %                                                                             %
1318 %                                                                             %
1319 %                                                                             %
1320 %   F i l e T o B l o b                                                       %
1321 %                                                                             %
1322 %                                                                             %
1323 %                                                                             %
1324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1325 %
1326 %  FileToBlob() returns the contents of a file as a buffer terminated with
1327 %  the '\0' character.  The length of the buffer (not including the extra
1328 %  terminating '\0' character) is returned via the 'length' parameter.  Free
1329 %  the buffer with RelinquishMagickMemory().
1330 %
1331 %  The format of the FileToBlob method is:
1332 %
1333 %      void *FileToBlob(const char *filename,const size_t extent,
1334 %        size_t *length,ExceptionInfo *exception)
1335 %
1336 %  A description of each parameter follows:
1337 %
1338 %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
1339 %      an error occurs NULL is returned.
1340 %
1341 %    o filename: the filename.
1342 %
1343 %    o extent:  The maximum length of the blob.
1344 %
1345 %    o length: On return, this reflects the actual length of the blob.
1346 %
1347 %    o exception: return any errors or warnings in this structure.
1348 %
1349 */
FileToBlob(const char * filename,const size_t extent,size_t * length,ExceptionInfo * exception)1350 MagickExport void *FileToBlob(const char *filename,const size_t extent,
1351   size_t *length,ExceptionInfo *exception)
1352 {
1353   int
1354     file;
1355 
1356   MagickBooleanType
1357     status;
1358 
1359   MagickOffsetType
1360     offset;
1361 
1362   register size_t
1363     i;
1364 
1365   ssize_t
1366     count;
1367 
1368   struct stat
1369     attributes;
1370 
1371   unsigned char
1372     *blob;
1373 
1374   void
1375     *map;
1376 
1377   assert(filename != (const char *) NULL);
1378   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1379   assert(exception != (ExceptionInfo *) NULL);
1380   *length=0;
1381   status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1382   if (status == MagickFalse)
1383     {
1384       errno=EPERM;
1385       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1386         "NotAuthorized","`%s'",filename);
1387       return(NULL);
1388     }
1389   file=fileno(stdin);
1390   if (LocaleCompare(filename,"-") != 0)
1391     {
1392       status=GetPathAttributes(filename,&attributes);
1393       if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1394         {
1395           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1396           return(NULL);
1397         }
1398       file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1399     }
1400   if (file == -1)
1401     {
1402       ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1403       return(NULL);
1404     }
1405   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1406   count=0;
1407   if ((file == fileno(stdin)) || (offset < 0) ||
1408       (offset != (MagickOffsetType) ((ssize_t) offset)))
1409     {
1410       size_t
1411         quantum;
1412 
1413       struct stat
1414         file_stats;
1415 
1416       /*
1417         Stream is not seekable.
1418       */
1419       offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1420       quantum=(size_t) MagickMaxBufferExtent;
1421       if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1422         quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1423       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1424       for (i=0; blob != (unsigned char *) NULL; i+=count)
1425       {
1426         count=read(file,blob+i,quantum);
1427         if (count <= 0)
1428           {
1429             count=0;
1430             if (errno != EINTR)
1431               break;
1432           }
1433         if (~((size_t) i) < (quantum+1))
1434           {
1435             blob=(unsigned char *) RelinquishMagickMemory(blob);
1436             break;
1437           }
1438         blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1439           sizeof(*blob));
1440         if ((size_t) (i+count) >= extent)
1441           break;
1442       }
1443       if (LocaleCompare(filename,"-") != 0)
1444         file=close(file);
1445       if (blob == (unsigned char *) NULL)
1446         {
1447           (void) ThrowMagickException(exception,GetMagickModule(),
1448             ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1449           return(NULL);
1450         }
1451       if (file == -1)
1452         {
1453           blob=(unsigned char *) RelinquishMagickMemory(blob);
1454           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1455           return(NULL);
1456         }
1457       *length=(size_t) MagickMin(i+count,extent);
1458       blob[*length]='\0';
1459       return(blob);
1460     }
1461   *length=(size_t) MagickMin(offset,(MagickOffsetType)
1462     MagickMin(extent,(size_t) SSIZE_MAX));
1463   blob=(unsigned char *) NULL;
1464   if (~(*length) >= (MagickPathExtent-1))
1465     blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1466       sizeof(*blob));
1467   if (blob == (unsigned char *) NULL)
1468     {
1469       file=close(file);
1470       (void) ThrowMagickException(exception,GetMagickModule(),
1471         ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1472       return(NULL);
1473     }
1474   map=MapBlob(file,ReadMode,0,*length);
1475   if (map != (unsigned char *) NULL)
1476     {
1477       (void) memcpy(blob,map,*length);
1478       (void) UnmapBlob(map,*length);
1479     }
1480   else
1481     {
1482       (void) lseek(file,0,SEEK_SET);
1483       for (i=0; i < *length; i+=count)
1484       {
1485         count=read(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
1486           SSIZE_MAX));
1487         if (count <= 0)
1488           {
1489             count=0;
1490             if (errno != EINTR)
1491               break;
1492           }
1493       }
1494       if (i < *length)
1495         {
1496           file=close(file)-1;
1497           blob=(unsigned char *) RelinquishMagickMemory(blob);
1498           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1499           return(NULL);
1500         }
1501     }
1502   blob[*length]='\0';
1503   if (LocaleCompare(filename,"-") != 0)
1504     file=close(file);
1505   if (file == -1)
1506     {
1507       blob=(unsigned char *) RelinquishMagickMemory(blob);
1508       ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1509     }
1510   return(blob);
1511 }
1512 
1513 /*
1514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1515 %                                                                             %
1516 %                                                                             %
1517 %                                                                             %
1518 %   F i l e T o I m a g e                                                     %
1519 %                                                                             %
1520 %                                                                             %
1521 %                                                                             %
1522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1523 %
1524 %  FileToImage() write the contents of a file to an image.
1525 %
1526 %  The format of the FileToImage method is:
1527 %
1528 %      MagickBooleanType FileToImage(Image *,const char *filename)
1529 %
1530 %  A description of each parameter follows:
1531 %
1532 %    o image: the image.
1533 %
1534 %    o filename: the filename.
1535 %
1536 */
1537 
WriteBlobStream(Image * image,const size_t length,const void * data)1538 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1539   const void *data)
1540 {
1541   BlobInfo
1542     *magick_restrict blob_info;
1543 
1544   MagickSizeType
1545     extent;
1546 
1547   register unsigned char
1548     *q;
1549 
1550   assert(image->blob != (BlobInfo *) NULL);
1551   assert(image->blob->type != UndefinedStream);
1552   assert(data != NULL);
1553   blob_info=image->blob;
1554   if (blob_info->type != BlobStream)
1555     return(WriteBlob(image,length,(const unsigned char *) data));
1556   extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1557   if (extent >= blob_info->extent)
1558     {
1559       extent=blob_info->extent+blob_info->quantum+length;
1560       blob_info->quantum<<=1;
1561       if (SetBlobExtent(image,extent) == MagickFalse)
1562         return(0);
1563     }
1564   q=blob_info->data+blob_info->offset;
1565   (void) memcpy(q,data,length);
1566   blob_info->offset+=length;
1567   if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1568     blob_info->length=(size_t) blob_info->offset;
1569   return((ssize_t) length);
1570 }
1571 
FileToImage(Image * image,const char * filename,ExceptionInfo * exception)1572 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1573   ExceptionInfo *exception)
1574 {
1575   int
1576     file;
1577 
1578   MagickBooleanType
1579     status;
1580 
1581   size_t
1582     length,
1583     quantum;
1584 
1585   ssize_t
1586     count;
1587 
1588   struct stat
1589     file_stats;
1590 
1591   unsigned char
1592     *blob;
1593 
1594   assert(image != (const Image *) NULL);
1595   assert(image->signature == MagickCoreSignature);
1596   assert(filename != (const char *) NULL);
1597   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1598   status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename);
1599   if (status == MagickFalse)
1600     {
1601       errno=EPERM;
1602       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1603         "NotAuthorized","`%s'",filename);
1604       return(MagickFalse);
1605     }
1606   file=fileno(stdin);
1607   if (LocaleCompare(filename,"-") != 0)
1608     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1609   if (file == -1)
1610     {
1611       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1612       return(MagickFalse);
1613     }
1614   quantum=(size_t) MagickMaxBufferExtent;
1615   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1616     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1617   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1618   if (blob == (unsigned char *) NULL)
1619     {
1620       file=close(file);
1621       ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1622         filename);
1623       return(MagickFalse);
1624     }
1625   for ( ; ; )
1626   {
1627     count=read(file,blob,quantum);
1628     if (count <= 0)
1629       {
1630         count=0;
1631         if (errno != EINTR)
1632           break;
1633       }
1634     length=(size_t) count;
1635     count=WriteBlobStream(image,length,blob);
1636     if (count != (ssize_t) length)
1637       {
1638         ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1639         break;
1640       }
1641   }
1642   file=close(file);
1643   if (file == -1)
1644     ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1645   blob=(unsigned char *) RelinquishMagickMemory(blob);
1646   return(MagickTrue);
1647 }
1648 
1649 /*
1650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1651 %                                                                             %
1652 %                                                                             %
1653 %                                                                             %
1654 +   G e t B l o b E r r o r                                                   %
1655 %                                                                             %
1656 %                                                                             %
1657 %                                                                             %
1658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1659 %
1660 %  GetBlobError() returns MagickTrue if the blob associated with the specified
1661 %  image encountered an error.
1662 %
1663 %  The format of the GetBlobError method is:
1664 %
1665 %       MagickBooleanType GetBlobError(const Image *image)
1666 %
1667 %  A description of each parameter follows:
1668 %
1669 %    o image: the image.
1670 %
1671 */
GetBlobError(const Image * image)1672 MagickExport MagickBooleanType GetBlobError(const Image *image)
1673 {
1674   assert(image != (const Image *) NULL);
1675   assert(image->signature == MagickCoreSignature);
1676   if (image->debug != MagickFalse)
1677     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1678   return(image->blob->status);
1679 }
1680 
1681 /*
1682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1683 %                                                                             %
1684 %                                                                             %
1685 %                                                                             %
1686 +   G e t B l o b F i l e H a n d l e                                         %
1687 %                                                                             %
1688 %                                                                             %
1689 %                                                                             %
1690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1691 %
1692 %  GetBlobFileHandle() returns the file handle associated with the image blob.
1693 %
1694 %  The format of the GetBlobFile method is:
1695 %
1696 %      FILE *GetBlobFileHandle(const Image *image)
1697 %
1698 %  A description of each parameter follows:
1699 %
1700 %    o image: the image.
1701 %
1702 */
GetBlobFileHandle(const Image * image)1703 MagickExport FILE *GetBlobFileHandle(const Image *image)
1704 {
1705   assert(image != (const Image *) NULL);
1706   assert(image->signature == MagickCoreSignature);
1707   return(image->blob->file_info.file);
1708 }
1709 
1710 /*
1711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1712 %                                                                             %
1713 %                                                                             %
1714 %                                                                             %
1715 +   G e t B l o b I n f o                                                     %
1716 %                                                                             %
1717 %                                                                             %
1718 %                                                                             %
1719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1720 %
1721 %  GetBlobInfo() initializes the BlobInfo structure.
1722 %
1723 %  The format of the GetBlobInfo method is:
1724 %
1725 %      void GetBlobInfo(BlobInfo *blob_info)
1726 %
1727 %  A description of each parameter follows:
1728 %
1729 %    o blob_info: Specifies a pointer to a BlobInfo structure.
1730 %
1731 */
GetBlobInfo(BlobInfo * blob_info)1732 MagickExport void GetBlobInfo(BlobInfo *blob_info)
1733 {
1734   assert(blob_info != (BlobInfo *) NULL);
1735   (void) memset(blob_info,0,sizeof(*blob_info));
1736   blob_info->type=UndefinedStream;
1737   blob_info->quantum=(size_t) MagickMaxBlobExtent;
1738   blob_info->properties.st_mtime=time((time_t *) NULL);
1739   blob_info->properties.st_ctime=blob_info->properties.st_mtime;
1740   blob_info->debug=IsEventLogging();
1741   blob_info->reference_count=1;
1742   blob_info->semaphore=AcquireSemaphoreInfo();
1743   blob_info->signature=MagickCoreSignature;
1744 }
1745 
1746 /*
1747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1748 %                                                                             %
1749 %                                                                             %
1750 %                                                                             %
1751 %  G e t B l o b P r o p e r t i e s                                          %
1752 %                                                                             %
1753 %                                                                             %
1754 %                                                                             %
1755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1756 %
1757 %  GetBlobProperties() returns information about an image blob.
1758 %
1759 %  The format of the GetBlobProperties method is:
1760 %
1761 %      const struct stat *GetBlobProperties(const Image *image)
1762 %
1763 %  A description of each parameter follows:
1764 %
1765 %    o image: the image.
1766 %
1767 */
GetBlobProperties(const Image * image)1768 MagickExport const struct stat *GetBlobProperties(const Image *image)
1769 {
1770   assert(image != (Image *) NULL);
1771   assert(image->signature == MagickCoreSignature);
1772   if (image->debug != MagickFalse)
1773     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1774   return(&image->blob->properties);
1775 }
1776 
1777 /*
1778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1779 %                                                                             %
1780 %                                                                             %
1781 %                                                                             %
1782 +  G e t B l o b S i z e                                                      %
1783 %                                                                             %
1784 %                                                                             %
1785 %                                                                             %
1786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1787 %
1788 %  GetBlobSize() returns the current length of the image file or blob; zero is
1789 %  returned if the size cannot be determined.
1790 %
1791 %  The format of the GetBlobSize method is:
1792 %
1793 %      MagickSizeType GetBlobSize(const Image *image)
1794 %
1795 %  A description of each parameter follows:
1796 %
1797 %    o image: the image.
1798 %
1799 */
GetBlobSize(const Image * image)1800 MagickExport MagickSizeType GetBlobSize(const Image *image)
1801 {
1802   BlobInfo
1803     *magick_restrict blob_info;
1804 
1805   MagickSizeType
1806     extent;
1807 
1808   assert(image != (Image *) NULL);
1809   assert(image->signature == MagickCoreSignature);
1810   if (image->debug != MagickFalse)
1811     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1812   assert(image->blob != (BlobInfo *) NULL);
1813   blob_info=image->blob;
1814   extent=0;
1815   switch (blob_info->type)
1816   {
1817     case UndefinedStream:
1818     case StandardStream:
1819     {
1820       extent=blob_info->size;
1821       break;
1822     }
1823     case FileStream:
1824     {
1825       if (fstat(fileno(blob_info->file_info.file),&blob_info->properties) == 0)
1826         extent=(MagickSizeType) blob_info->properties.st_size;
1827       break;
1828     }
1829     case PipeStream:
1830     {
1831       extent=blob_info->size;
1832       break;
1833     }
1834     case ZipStream:
1835     case BZipStream:
1836     {
1837       MagickBooleanType
1838         status;
1839 
1840       status=GetPathAttributes(image->filename,&blob_info->properties);
1841       if (status != MagickFalse)
1842         extent=(MagickSizeType) blob_info->properties.st_size;
1843       break;
1844     }
1845     case FifoStream:
1846       break;
1847     case BlobStream:
1848     {
1849       extent=(MagickSizeType) blob_info->length;
1850       break;
1851     }
1852     case CustomStream:
1853     {
1854       if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
1855           (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
1856         {
1857           MagickOffsetType
1858             offset;
1859 
1860           offset=blob_info->custom_stream->teller(
1861             blob_info->custom_stream->data);
1862           extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
1863             blob_info->custom_stream->data);
1864           (void) blob_info->custom_stream->seeker(offset,SEEK_SET,
1865             blob_info->custom_stream->data);
1866         }
1867       break;
1868     }
1869   }
1870   return(extent);
1871 }
1872 
1873 /*
1874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1875 %                                                                             %
1876 %                                                                             %
1877 %                                                                             %
1878 +   G e t B l o b S t r e a m D a t a                                         %
1879 %                                                                             %
1880 %                                                                             %
1881 %                                                                             %
1882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1883 %
1884 %  GetBlobStreamData() returns the stream data for the image.
1885 %
1886 %  The format of the GetBlobStreamData method is:
1887 %
1888 %      void *GetBlobStreamData(const Image *image)
1889 %
1890 %  A description of each parameter follows:
1891 %
1892 %    o image: the image.
1893 %
1894 */
GetBlobStreamData(const Image * image)1895 MagickExport void *GetBlobStreamData(const Image *image)
1896 {
1897   assert(image != (const Image *) NULL);
1898   assert(image->signature == MagickCoreSignature);
1899   return(image->blob->data);
1900 }
1901 
1902 /*
1903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1904 %                                                                             %
1905 %                                                                             %
1906 %                                                                             %
1907 +   G e t B l o b S t r e a m H a n d l e r                                   %
1908 %                                                                             %
1909 %                                                                             %
1910 %                                                                             %
1911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1912 %
1913 %  GetBlobStreamHandler() returns the stream handler for the image.
1914 %
1915 %  The format of the GetBlobStreamHandler method is:
1916 %
1917 %      StreamHandler GetBlobStreamHandler(const Image *image)
1918 %
1919 %  A description of each parameter follows:
1920 %
1921 %    o image: the image.
1922 %
1923 */
GetBlobStreamHandler(const Image * image)1924 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1925 {
1926   assert(image != (const Image *) NULL);
1927   assert(image->signature == MagickCoreSignature);
1928   if (image->debug != MagickFalse)
1929     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1930   return(image->blob->stream);
1931 }
1932 
1933 /*
1934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1935 %                                                                             %
1936 %                                                                             %
1937 %                                                                             %
1938 %   I m a g e T o B l o b                                                     %
1939 %                                                                             %
1940 %                                                                             %
1941 %                                                                             %
1942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1943 %
1944 %  ImageToBlob() implements direct to memory image formats.  It returns the
1945 %  image as a formatted blob and its length.  The magick member of the Image
1946 %  structure determines the format of the returned blob (GIF, JPEG, PNG,
1947 %  etc.).  This method is the equivalent of WriteImage(), but writes the
1948 %  formatted "file" to a memory buffer rather than to an actual file.
1949 %
1950 %  The format of the ImageToBlob method is:
1951 %
1952 %      void *ImageToBlob(const ImageInfo *image_info,Image *image,
1953 %        size_t *length,ExceptionInfo *exception)
1954 %
1955 %  A description of each parameter follows:
1956 %
1957 %    o image_info: the image info.
1958 %
1959 %    o image: the image.
1960 %
1961 %    o length: return the actual length of the blob.
1962 %
1963 %    o exception: return any errors or warnings in this structure.
1964 %
1965 */
ImageToBlob(const ImageInfo * image_info,Image * image,size_t * length,ExceptionInfo * exception)1966 MagickExport void *ImageToBlob(const ImageInfo *image_info,
1967   Image *image,size_t *length,ExceptionInfo *exception)
1968 {
1969   const MagickInfo
1970     *magick_info;
1971 
1972   ImageInfo
1973     *blob_info;
1974 
1975   MagickBooleanType
1976     status;
1977 
1978   void
1979     *blob;
1980 
1981   assert(image_info != (const ImageInfo *) NULL);
1982   assert(image_info->signature == MagickCoreSignature);
1983   if (image_info->debug != MagickFalse)
1984     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1985       image_info->filename);
1986   assert(image != (Image *) NULL);
1987   assert(image->signature == MagickCoreSignature);
1988   assert(exception != (ExceptionInfo *) NULL);
1989   *length=0;
1990   blob=(unsigned char *) NULL;
1991   blob_info=CloneImageInfo(image_info);
1992   blob_info->adjoin=MagickFalse;
1993   (void) SetImageInfo(blob_info,1,exception);
1994   if (*blob_info->magick != '\0')
1995     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1996   magick_info=GetMagickInfo(image->magick,exception);
1997   if (magick_info == (const MagickInfo *) NULL)
1998     {
1999       (void) ThrowMagickException(exception,GetMagickModule(),
2000         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2001         image->magick);
2002       blob_info=DestroyImageInfo(blob_info);
2003       return(blob);
2004     }
2005   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
2006   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2007     {
2008       /*
2009         Native blob support for this image format.
2010       */
2011       blob_info->length=0;
2012       blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2013         sizeof(unsigned char));
2014       if (blob_info->blob == NULL)
2015         (void) ThrowMagickException(exception,GetMagickModule(),
2016           ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2017       else
2018         {
2019           (void) CloseBlob(image);
2020           image->blob->exempt=MagickTrue;
2021           *image->filename='\0';
2022           status=WriteImage(blob_info,image,exception);
2023           *length=image->blob->length;
2024           blob=DetachBlob(image->blob);
2025           if (blob == (void *) NULL)
2026             blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2027           else if (status == MagickFalse)
2028             blob=RelinquishMagickMemory(blob);
2029           else
2030             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2031         }
2032     }
2033   else
2034     {
2035       char
2036         unique[MagickPathExtent];
2037 
2038       int
2039         file;
2040 
2041       /*
2042         Write file to disk in blob image format.
2043       */
2044       file=AcquireUniqueFileResource(unique);
2045       if (file == -1)
2046         {
2047           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2048             image_info->filename);
2049         }
2050       else
2051         {
2052           blob_info->file=fdopen(file,"wb");
2053           if (blob_info->file != (FILE *) NULL)
2054             {
2055               (void) FormatLocaleString(image->filename,MagickPathExtent,
2056                 "%s:%s",image->magick,unique);
2057               status=WriteImage(blob_info,image,exception);
2058               (void) CloseBlob(image);
2059               (void) fclose(blob_info->file);
2060               if (status != MagickFalse)
2061                 blob=FileToBlob(unique,~0UL,length,exception);
2062             }
2063           (void) RelinquishUniqueFileResource(unique);
2064         }
2065     }
2066   blob_info=DestroyImageInfo(blob_info);
2067   return(blob);
2068 }
2069 
2070 /*
2071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2072 %                                                                             %
2073 %                                                                             %
2074 %                                                                             %
2075 +  I m a g e T o C u s t o m S t r e a m                                      %
2076 %                                                                             %
2077 %                                                                             %
2078 %                                                                             %
2079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2080 %
2081 %  ImageToCustomStream() is the equivalent of WriteImage(), but writes the
2082 %  formatted "file" to the custom stream rather than to an actual file.
2083 %
2084 %  The format of the ImageToCustomStream method is:
2085 %
2086 %      void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2087 %        ExceptionInfo *exception)
2088 %
2089 %  A description of each parameter follows:
2090 %
2091 %    o image_info: the image info.
2092 %
2093 %    o image: the image.
2094 %
2095 %    o exception: return any errors or warnings in this structure.
2096 %
2097 */
ImageToCustomStream(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)2098 MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2099   ExceptionInfo *exception)
2100 {
2101   const MagickInfo
2102     *magick_info;
2103 
2104   ImageInfo
2105     *clone_info;
2106 
2107   MagickBooleanType
2108     blob_support,
2109     status;
2110 
2111   assert(image_info != (const ImageInfo *) NULL);
2112   assert(image_info->signature == MagickCoreSignature);
2113   if (image_info->debug != MagickFalse)
2114     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2115       image_info->filename);
2116   assert(image != (Image *) NULL);
2117   assert(image->signature == MagickCoreSignature);
2118   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2119   assert(image_info->custom_stream->signature == MagickCoreSignature);
2120   assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2121   assert(exception != (ExceptionInfo *) NULL);
2122   clone_info=CloneImageInfo(image_info);
2123   clone_info->adjoin=MagickFalse;
2124   (void) SetImageInfo(clone_info,1,exception);
2125   if (*clone_info->magick != '\0')
2126     (void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
2127   magick_info=GetMagickInfo(image->magick,exception);
2128   if (magick_info == (const MagickInfo *) NULL)
2129     {
2130       (void) ThrowMagickException(exception,GetMagickModule(),
2131         MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2132         image->magick);
2133       clone_info=DestroyImageInfo(clone_info);
2134       return;
2135     }
2136   (void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
2137   blob_support=GetMagickBlobSupport(magick_info);
2138   if ((blob_support != MagickFalse) &&
2139       (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2140     {
2141       if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2142           (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2143         blob_support=MagickFalse;
2144     }
2145   if (blob_support != MagickFalse)
2146     {
2147       /*
2148         Native blob support for this image format.
2149       */
2150       (void) CloseBlob(image);
2151       *image->filename='\0';
2152       (void) WriteImage(clone_info,image,exception);
2153       (void) CloseBlob(image);
2154     }
2155   else
2156     {
2157       char
2158         unique[MagickPathExtent];
2159 
2160       int
2161         file;
2162 
2163       unsigned char
2164         *blob;
2165 
2166       /*
2167         Write file to disk in blob image format.
2168       */
2169       clone_info->custom_stream=(CustomStreamInfo *) NULL;
2170       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2171         sizeof(*blob));
2172       if (blob == (unsigned char *) NULL)
2173         {
2174           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2175             image_info->filename);
2176           clone_info=DestroyImageInfo(clone_info);
2177           return;
2178         }
2179       file=AcquireUniqueFileResource(unique);
2180       if (file == -1)
2181         {
2182           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2183             image_info->filename);
2184           blob=(unsigned char *) RelinquishMagickMemory(blob);
2185           clone_info=DestroyImageInfo(clone_info);
2186           return;
2187         }
2188       clone_info->file=fdopen(file,"wb+");
2189       if (clone_info->file != (FILE *) NULL)
2190         {
2191           ssize_t
2192             count;
2193 
2194           (void) FormatLocaleString(image->filename,MagickPathExtent,
2195             "%s:%s",image->magick,unique);
2196           status=WriteImage(clone_info,image,exception);
2197           (void) CloseBlob(image);
2198           if (status != MagickFalse)
2199             {
2200               (void) fseek(clone_info->file,0,SEEK_SET);
2201               count=(ssize_t) MagickMaxBufferExtent;
2202               while (count == (ssize_t) MagickMaxBufferExtent)
2203               {
2204                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2205                   clone_info->file);
2206                 (void) image_info->custom_stream->writer(blob,(size_t) count,
2207                   image_info->custom_stream->data);
2208               }
2209             }
2210           (void) fclose(clone_info->file);
2211         }
2212       blob=(unsigned char *) RelinquishMagickMemory(blob);
2213       (void) RelinquishUniqueFileResource(unique);
2214     }
2215   clone_info=DestroyImageInfo(clone_info);
2216 }
2217 
2218 /*
2219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2220 %                                                                             %
2221 %                                                                             %
2222 %                                                                             %
2223 %   I m a g e T o F i l e                                                     %
2224 %                                                                             %
2225 %                                                                             %
2226 %                                                                             %
2227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2228 %
2229 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
2230 %  occurs otherwise MagickTrue.
2231 %
2232 %  The format of the ImageToFile method is:
2233 %
2234 %       MagickBooleanType ImageToFile(Image *image,char *filename,
2235 %         ExceptionInfo *exception)
2236 %
2237 %  A description of each parameter follows:
2238 %
2239 %    o image: the image.
2240 %
2241 %    o filename: Write the image to this file.
2242 %
2243 %    o exception: return any errors or warnings in this structure.
2244 %
2245 */
ImageToFile(Image * image,char * filename,ExceptionInfo * exception)2246 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
2247   ExceptionInfo *exception)
2248 {
2249   int
2250     file;
2251 
2252   register const unsigned char
2253     *p;
2254 
2255   register size_t
2256     i;
2257 
2258   size_t
2259     length,
2260     quantum;
2261 
2262   ssize_t
2263     count;
2264 
2265   struct stat
2266     file_stats;
2267 
2268   unsigned char
2269     *buffer;
2270 
2271   assert(image != (Image *) NULL);
2272   assert(image->signature == MagickCoreSignature);
2273   assert(image->blob != (BlobInfo *) NULL);
2274   assert(image->blob->type != UndefinedStream);
2275   if (image->debug != MagickFalse)
2276     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
2277   assert(filename != (const char *) NULL);
2278   if (*filename == '\0')
2279     file=AcquireUniqueFileResource(filename);
2280   else
2281     if (LocaleCompare(filename,"-") == 0)
2282       file=fileno(stdout);
2283     else
2284       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
2285   if (file == -1)
2286     {
2287       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2288       return(MagickFalse);
2289     }
2290   quantum=(size_t) MagickMaxBufferExtent;
2291   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2292     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2293   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2294   if (buffer == (unsigned char *) NULL)
2295     {
2296       file=close(file)-1;
2297       (void) ThrowMagickException(exception,GetMagickModule(),
2298         ResourceLimitError,"MemoryAllocationError","`%s'",filename);
2299       return(MagickFalse);
2300     }
2301   length=0;
2302   p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2303   for (i=0; count > 0; )
2304   {
2305     length=(size_t) count;
2306     for (i=0; i < length; i+=count)
2307     {
2308       count=write(file,p+i,(size_t) (length-i));
2309       if (count <= 0)
2310         {
2311           count=0;
2312           if (errno != EINTR)
2313             break;
2314         }
2315     }
2316     if (i < length)
2317       break;
2318     p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2319   }
2320   if (LocaleCompare(filename,"-") != 0)
2321     file=close(file);
2322   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2323   if ((file == -1) || (i < length))
2324     {
2325       if (file != -1)
2326         file=close(file);
2327       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2328       return(MagickFalse);
2329     }
2330   return(MagickTrue);
2331 }
2332 
2333 /*
2334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335 %                                                                             %
2336 %                                                                             %
2337 %                                                                             %
2338 %   I m a g e s T o B l o b                                                   %
2339 %                                                                             %
2340 %                                                                             %
2341 %                                                                             %
2342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2343 %
2344 %  ImagesToBlob() implements direct to memory image formats.  It returns the
2345 %  image sequence as a blob and its length.  The magick member of the ImageInfo
2346 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
2347 %
2348 %  Note, some image formats do not permit multiple images to the same image
2349 %  stream (e.g. JPEG).  in this instance, just the first image of the
2350 %  sequence is returned as a blob.
2351 %
2352 %  The format of the ImagesToBlob method is:
2353 %
2354 %      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2355 %        size_t *length,ExceptionInfo *exception)
2356 %
2357 %  A description of each parameter follows:
2358 %
2359 %    o image_info: the image info.
2360 %
2361 %    o images: the image list.
2362 %
2363 %    o length: return the actual length of the blob.
2364 %
2365 %    o exception: return any errors or warnings in this structure.
2366 %
2367 */
ImagesToBlob(const ImageInfo * image_info,Image * images,size_t * length,ExceptionInfo * exception)2368 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2369   size_t *length,ExceptionInfo *exception)
2370 {
2371   const MagickInfo
2372     *magick_info;
2373 
2374   ImageInfo
2375     *clone_info;
2376 
2377   MagickBooleanType
2378     status;
2379 
2380   void
2381     *blob;
2382 
2383   assert(image_info != (const ImageInfo *) NULL);
2384   assert(image_info->signature == MagickCoreSignature);
2385   if (image_info->debug != MagickFalse)
2386     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2387       image_info->filename);
2388   assert(images != (Image *) NULL);
2389   assert(images->signature == MagickCoreSignature);
2390   assert(exception != (ExceptionInfo *) NULL);
2391   *length=0;
2392   blob=(unsigned char *) NULL;
2393   clone_info=CloneImageInfo(image_info);
2394   (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2395     exception);
2396   if (*clone_info->magick != '\0')
2397     (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2398   magick_info=GetMagickInfo(images->magick,exception);
2399   if (magick_info == (const MagickInfo *) NULL)
2400     {
2401       (void) ThrowMagickException(exception,GetMagickModule(),
2402         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2403         images->magick);
2404       clone_info=DestroyImageInfo(clone_info);
2405       return(blob);
2406     }
2407   if (GetMagickAdjoin(magick_info) == MagickFalse)
2408     {
2409       clone_info=DestroyImageInfo(clone_info);
2410       return(ImageToBlob(image_info,images,length,exception));
2411     }
2412   (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2413   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2414     {
2415       /*
2416         Native blob support for this images format.
2417       */
2418       clone_info->length=0;
2419       clone_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2420         sizeof(unsigned char));
2421       if (clone_info->blob == (void *) NULL)
2422         (void) ThrowMagickException(exception,GetMagickModule(),
2423           ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2424       else
2425         {
2426           (void) CloseBlob(images);
2427           images->blob->exempt=MagickTrue;
2428           *images->filename='\0';
2429           status=WriteImages(clone_info,images,images->filename,exception);
2430           *length=images->blob->length;
2431           blob=DetachBlob(images->blob);
2432           if (blob == (void *) NULL)
2433             clone_info->blob=RelinquishMagickMemory(clone_info->blob);
2434           else if (status == MagickFalse)
2435             blob=RelinquishMagickMemory(blob);
2436           else
2437             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2438         }
2439     }
2440   else
2441     {
2442       char
2443         filename[MagickPathExtent],
2444         unique[MagickPathExtent];
2445 
2446       int
2447         file;
2448 
2449       /*
2450         Write file to disk in blob images format.
2451       */
2452       file=AcquireUniqueFileResource(unique);
2453       if (file == -1)
2454         {
2455           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2456             image_info->filename);
2457         }
2458       else
2459         {
2460           clone_info->file=fdopen(file,"wb");
2461           if (clone_info->file != (FILE *) NULL)
2462             {
2463               (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2464                 images->magick,unique);
2465               status=WriteImages(clone_info,images,filename,exception);
2466               (void) CloseBlob(images);
2467               (void) fclose(clone_info->file);
2468               if (status != MagickFalse)
2469                 blob=FileToBlob(unique,~0UL,length,exception);
2470             }
2471           (void) RelinquishUniqueFileResource(unique);
2472         }
2473     }
2474   clone_info=DestroyImageInfo(clone_info);
2475   return(blob);
2476 }
2477 
2478 /*
2479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2480 %                                                                             %
2481 %                                                                             %
2482 %                                                                             %
2483 +  I m a g e s T o C u s t o m B l o b                                        %
2484 %                                                                             %
2485 %                                                                             %
2486 %                                                                             %
2487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2488 %
2489 %  ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2490 %  formatted "file" to the custom stream rather than to an actual file.
2491 %
2492 %  The format of the ImageToCustomStream method is:
2493 %
2494 %      void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2495 %        ExceptionInfo *exception)
2496 %
2497 %  A description of each parameter follows:
2498 %
2499 %    o image_info: the image info.
2500 %
2501 %    o images: the image list.
2502 %
2503 %    o exception: return any errors or warnings in this structure.
2504 %
2505 */
ImagesToCustomStream(const ImageInfo * image_info,Image * images,ExceptionInfo * exception)2506 MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2507   Image *images,ExceptionInfo *exception)
2508 {
2509   const MagickInfo
2510     *magick_info;
2511 
2512   ImageInfo
2513     *clone_info;
2514 
2515   MagickBooleanType
2516     blob_support,
2517     status;
2518 
2519   assert(image_info != (const ImageInfo *) NULL);
2520   assert(image_info->signature == MagickCoreSignature);
2521   if (image_info->debug != MagickFalse)
2522     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2523       image_info->filename);
2524   assert(images != (Image *) NULL);
2525   assert(images->signature == MagickCoreSignature);
2526   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2527   assert(image_info->custom_stream->signature == MagickCoreSignature);
2528   assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
2529   assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2530   assert(exception != (ExceptionInfo *) NULL);
2531   clone_info=CloneImageInfo(image_info);
2532   (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2533     exception);
2534   if (*clone_info->magick != '\0')
2535     (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2536   magick_info=GetMagickInfo(images->magick,exception);
2537   if (magick_info == (const MagickInfo *) NULL)
2538     {
2539       (void) ThrowMagickException(exception,GetMagickModule(),
2540         MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2541         images->magick);
2542       clone_info=DestroyImageInfo(clone_info);
2543       return;
2544     }
2545   (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2546   blob_support=GetMagickBlobSupport(magick_info);
2547   if ((blob_support != MagickFalse) &&
2548       (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2549     {
2550       if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2551           (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2552         blob_support=MagickFalse;
2553     }
2554   if (blob_support != MagickFalse)
2555     {
2556       /*
2557         Native blob support for this image format.
2558       */
2559       (void) CloseBlob(images);
2560       *images->filename='\0';
2561       (void) WriteImages(clone_info,images,images->filename,exception);
2562       (void) CloseBlob(images);
2563     }
2564   else
2565     {
2566       char
2567         filename[MagickPathExtent],
2568         unique[MagickPathExtent];
2569 
2570       int
2571         file;
2572 
2573       unsigned char
2574         *blob;
2575 
2576       /*
2577         Write file to disk in blob image format.
2578       */
2579       clone_info->custom_stream=(CustomStreamInfo *) NULL;
2580       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2581         sizeof(*blob));
2582       if (blob == (unsigned char *) NULL)
2583         {
2584           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2585             image_info->filename);
2586           clone_info=DestroyImageInfo(clone_info);
2587           return;
2588         }
2589       file=AcquireUniqueFileResource(unique);
2590       if (file == -1)
2591         {
2592           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2593             image_info->filename);
2594           blob=(unsigned char *) RelinquishMagickMemory(blob);
2595           clone_info=DestroyImageInfo(clone_info);
2596           return;
2597         }
2598       clone_info->file=fdopen(file,"wb+");
2599       if (clone_info->file != (FILE *) NULL)
2600         {
2601           ssize_t
2602             count;
2603 
2604           (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2605             images->magick,unique);
2606           status=WriteImages(clone_info,images,filename,exception);
2607           (void) CloseBlob(images);
2608           if (status != MagickFalse)
2609             {
2610               (void) fseek(clone_info->file,0,SEEK_SET);
2611               count=(ssize_t) MagickMaxBufferExtent;
2612               while (count == (ssize_t) MagickMaxBufferExtent)
2613               {
2614                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2615                   clone_info->file);
2616                 (void) image_info->custom_stream->writer(blob,(size_t) count,
2617                   image_info->custom_stream->data);
2618               }
2619             }
2620           (void) fclose(clone_info->file);
2621         }
2622       blob=(unsigned char *) RelinquishMagickMemory(blob);
2623       (void) RelinquishUniqueFileResource(unique);
2624     }
2625   clone_info=DestroyImageInfo(clone_info);
2626 }
2627 
2628 /*
2629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2630 %                                                                             %
2631 %                                                                             %
2632 %                                                                             %
2633 %   I n j e c t I m a g e B l o b                                             %
2634 %                                                                             %
2635 %                                                                             %
2636 %                                                                             %
2637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2638 %
2639 %  InjectImageBlob() injects the image with a copy of itself in the specified
2640 %  format (e.g. inject JPEG into a PDF image).
2641 %
2642 %  The format of the InjectImageBlob method is:
2643 %
2644 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2645 %        Image *image,Image *inject_image,const char *format,
2646 %        ExceptionInfo *exception)
2647 %
2648 %  A description of each parameter follows:
2649 %
2650 %    o image_info: the image info..
2651 %
2652 %    o image: the image.
2653 %
2654 %    o inject_image: inject into the image stream.
2655 %
2656 %    o format: the image format.
2657 %
2658 %    o exception: return any errors or warnings in this structure.
2659 %
2660 */
InjectImageBlob(const ImageInfo * image_info,Image * image,Image * inject_image,const char * format,ExceptionInfo * exception)2661 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2662   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2663 {
2664   char
2665     filename[MagickPathExtent];
2666 
2667   FILE
2668     *unique_file;
2669 
2670   Image
2671     *byte_image;
2672 
2673   ImageInfo
2674     *write_info;
2675 
2676   int
2677     file;
2678 
2679   MagickBooleanType
2680     status;
2681 
2682   register ssize_t
2683     i;
2684 
2685   size_t
2686     quantum;
2687 
2688   ssize_t
2689     count;
2690 
2691   struct stat
2692     file_stats;
2693 
2694   unsigned char
2695     *buffer;
2696 
2697   /*
2698     Write inject image to a temporary file.
2699   */
2700   assert(image_info != (ImageInfo *) NULL);
2701   assert(image_info->signature == MagickCoreSignature);
2702   assert(image != (Image *) NULL);
2703   assert(image->signature == MagickCoreSignature);
2704   if (image->debug != MagickFalse)
2705     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2706   assert(inject_image != (Image *) NULL);
2707   assert(inject_image->signature == MagickCoreSignature);
2708   assert(exception != (ExceptionInfo *) NULL);
2709   unique_file=(FILE *) NULL;
2710   file=AcquireUniqueFileResource(filename);
2711   if (file != -1)
2712     unique_file=fdopen(file,"wb");
2713   if ((file == -1) || (unique_file == (FILE *) NULL))
2714     {
2715       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2716       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2717         image->filename);
2718       return(MagickFalse);
2719     }
2720   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2721   if (byte_image == (Image *) NULL)
2722     {
2723       (void) fclose(unique_file);
2724       (void) RelinquishUniqueFileResource(filename);
2725       return(MagickFalse);
2726     }
2727   (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2728     format,filename);
2729   DestroyBlob(byte_image);
2730   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2731   write_info=CloneImageInfo(image_info);
2732   SetImageInfoFile(write_info,unique_file);
2733   status=WriteImage(write_info,byte_image,exception);
2734   write_info=DestroyImageInfo(write_info);
2735   byte_image=DestroyImage(byte_image);
2736   (void) fclose(unique_file);
2737   if (status == MagickFalse)
2738     {
2739       (void) RelinquishUniqueFileResource(filename);
2740       return(MagickFalse);
2741     }
2742   /*
2743     Inject into image stream.
2744   */
2745   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2746   if (file == -1)
2747     {
2748       (void) RelinquishUniqueFileResource(filename);
2749       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2750         image_info->filename);
2751       return(MagickFalse);
2752     }
2753   quantum=(size_t) MagickMaxBufferExtent;
2754   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2755     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2756   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2757   if (buffer == (unsigned char *) NULL)
2758     {
2759       (void) RelinquishUniqueFileResource(filename);
2760       file=close(file);
2761       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2762         image->filename);
2763     }
2764   for (i=0; ; i+=count)
2765   {
2766     count=read(file,buffer,quantum);
2767     if (count <= 0)
2768       {
2769         count=0;
2770         if (errno != EINTR)
2771           break;
2772       }
2773     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2774       MagickFalse;
2775   }
2776   file=close(file);
2777   if (file == -1)
2778     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2779   (void) RelinquishUniqueFileResource(filename);
2780   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2781   return(status);
2782 }
2783 
2784 /*
2785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2786 %                                                                             %
2787 %                                                                             %
2788 %                                                                             %
2789 %   I s B l o b E x e m p t                                                   %
2790 %                                                                             %
2791 %                                                                             %
2792 %                                                                             %
2793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2794 %
2795 %  IsBlobExempt() returns true if the blob is exempt.
2796 %
2797 %  The format of the IsBlobExempt method is:
2798 %
2799 %       MagickBooleanType IsBlobExempt(const Image *image)
2800 %
2801 %  A description of each parameter follows:
2802 %
2803 %    o image: the image.
2804 %
2805 */
IsBlobExempt(const Image * image)2806 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2807 {
2808   assert(image != (const Image *) NULL);
2809   assert(image->signature == MagickCoreSignature);
2810   if (image->debug != MagickFalse)
2811     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2812   return(image->blob->exempt);
2813 }
2814 
2815 /*
2816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2817 %                                                                             %
2818 %                                                                             %
2819 %                                                                             %
2820 %   I s B l o b S e e k a b l e                                               %
2821 %                                                                             %
2822 %                                                                             %
2823 %                                                                             %
2824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2825 %
2826 %  IsBlobSeekable() returns true if the blob is seekable.
2827 %
2828 %  The format of the IsBlobSeekable method is:
2829 %
2830 %       MagickBooleanType IsBlobSeekable(const Image *image)
2831 %
2832 %  A description of each parameter follows:
2833 %
2834 %    o image: the image.
2835 %
2836 */
IsBlobSeekable(const Image * image)2837 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2838 {
2839   BlobInfo
2840     *magick_restrict blob_info;
2841 
2842   assert(image != (const Image *) NULL);
2843   assert(image->signature == MagickCoreSignature);
2844   if (image->debug != MagickFalse)
2845     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2846   blob_info=image->blob;
2847   switch (blob_info->type)
2848   {
2849     case BlobStream:
2850       return(MagickTrue);
2851     case FileStream:
2852     {
2853       int
2854         status;
2855 
2856       if (blob_info->file_info.file == (FILE *) NULL)
2857         return(MagickFalse);
2858       status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2859       return(status == -1 ? MagickFalse : MagickTrue);
2860     }
2861     case ZipStream:
2862     {
2863 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2864       MagickOffsetType
2865         offset;
2866 
2867       if (blob_info->file_info.gzfile == (gzFile) NULL)
2868         return(MagickFalse);
2869       offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2870       return(offset < 0 ? MagickFalse : MagickTrue);
2871 #else
2872       break;
2873 #endif
2874     }
2875     case UndefinedStream:
2876     case BZipStream:
2877     case FifoStream:
2878     case PipeStream:
2879     case StandardStream:
2880       break;
2881     case CustomStream:
2882     {
2883       if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
2884           (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
2885         return(MagickTrue);
2886       break;
2887     }
2888     default:
2889       break;
2890   }
2891   return(MagickFalse);
2892 }
2893 
2894 /*
2895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2896 %                                                                             %
2897 %                                                                             %
2898 %                                                                             %
2899 %   I s B l o b T e m p o r a r y                                             %
2900 %                                                                             %
2901 %                                                                             %
2902 %                                                                             %
2903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2904 %
2905 %  IsBlobTemporary() returns true if the blob is temporary.
2906 %
2907 %  The format of the IsBlobTemporary method is:
2908 %
2909 %       MagickBooleanType IsBlobTemporary(const Image *image)
2910 %
2911 %  A description of each parameter follows:
2912 %
2913 %    o image: the image.
2914 %
2915 */
IsBlobTemporary(const Image * image)2916 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2917 {
2918   assert(image != (const Image *) NULL);
2919   assert(image->signature == MagickCoreSignature);
2920   if (image->debug != MagickFalse)
2921     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2922   return(image->blob->temporary);
2923 }
2924 
2925 /*
2926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2927 %                                                                             %
2928 %                                                                             %
2929 %                                                                             %
2930 +  M a p B l o b                                                              %
2931 %                                                                             %
2932 %                                                                             %
2933 %                                                                             %
2934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2935 %
2936 %  MapBlob() creates a mapping from a file to a binary large object.
2937 %
2938 %  The format of the MapBlob method is:
2939 %
2940 %      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2941 %        const size_t length)
2942 %
2943 %  A description of each parameter follows:
2944 %
2945 %    o file: map this file descriptor.
2946 %
2947 %    o mode: ReadMode, WriteMode, or IOMode.
2948 %
2949 %    o offset: starting at this offset within the file.
2950 %
2951 %    o length: the length of the mapping is returned in this pointer.
2952 %
2953 */
MapBlob(int file,const MapMode mode,const MagickOffsetType offset,const size_t length)2954 MagickExport void *MapBlob(int file,const MapMode mode,
2955   const MagickOffsetType offset,const size_t length)
2956 {
2957 #if defined(MAGICKCORE_HAVE_MMAP)
2958   int
2959     flags,
2960     protection;
2961 
2962   void
2963     *map;
2964 
2965   /*
2966     Map file.
2967   */
2968   flags=0;
2969   if (file == -1)
2970 #if defined(MAP_ANONYMOUS)
2971     flags|=MAP_ANONYMOUS;
2972 #else
2973     return(NULL);
2974 #endif
2975   switch (mode)
2976   {
2977     case ReadMode:
2978     default:
2979     {
2980       protection=PROT_READ;
2981       flags|=MAP_PRIVATE;
2982       break;
2983     }
2984     case WriteMode:
2985     {
2986       protection=PROT_WRITE;
2987       flags|=MAP_SHARED;
2988       break;
2989     }
2990     case IOMode:
2991     {
2992       protection=PROT_READ | PROT_WRITE;
2993       flags|=MAP_SHARED;
2994       break;
2995     }
2996   }
2997 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2998   map=mmap((char *) NULL,length,protection,flags,file,offset);
2999 #else
3000   map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,offset);
3001   if (map == MAP_FAILED)
3002     map=mmap((char *) NULL,length,protection,flags,file,offset);
3003 #endif
3004   if (map == MAP_FAILED)
3005     return(NULL);
3006   return(map);
3007 #else
3008   (void) file;
3009   (void) mode;
3010   (void) offset;
3011   (void) length;
3012   return(NULL);
3013 #endif
3014 }
3015 
3016 /*
3017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3018 %                                                                             %
3019 %                                                                             %
3020 %                                                                             %
3021 +  M S B O r d e r L o n g                                                    %
3022 %                                                                             %
3023 %                                                                             %
3024 %                                                                             %
3025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3026 %
3027 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
3028 %  most-significant byte first.
3029 %
3030 %  The format of the MSBOrderLong method is:
3031 %
3032 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
3033 %
3034 %  A description of each parameter follows.
3035 %
3036 %   o  buffer:  Specifies a pointer to a buffer of integers.
3037 %
3038 %   o  length:  Specifies the length of the buffer.
3039 %
3040 */
MSBOrderLong(unsigned char * buffer,const size_t length)3041 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
3042 {
3043   int
3044     c;
3045 
3046   register unsigned char
3047     *p,
3048     *q;
3049 
3050   assert(buffer != (unsigned char *) NULL);
3051   q=buffer+length;
3052   while (buffer < q)
3053   {
3054     p=buffer+3;
3055     c=(int) (*p);
3056     *p=(*buffer);
3057     *buffer++=(unsigned char) c;
3058     p=buffer+1;
3059     c=(int) (*p);
3060     *p=(*buffer);
3061     *buffer++=(unsigned char) c;
3062     buffer+=2;
3063   }
3064 }
3065 
3066 /*
3067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3068 %                                                                             %
3069 %                                                                             %
3070 %                                                                             %
3071 +  M S B O r d e r S h o r t                                                  %
3072 %                                                                             %
3073 %                                                                             %
3074 %                                                                             %
3075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3076 %
3077 %  MSBOrderShort() converts a least-significant byte first buffer of integers
3078 %  to most-significant byte first.
3079 %
3080 %  The format of the MSBOrderShort method is:
3081 %
3082 %      void MSBOrderShort(unsigned char *p,const size_t length)
3083 %
3084 %  A description of each parameter follows.
3085 %
3086 %   o  p:  Specifies a pointer to a buffer of integers.
3087 %
3088 %   o  length:  Specifies the length of the buffer.
3089 %
3090 */
MSBOrderShort(unsigned char * p,const size_t length)3091 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
3092 {
3093   int
3094     c;
3095 
3096   register unsigned char
3097     *q;
3098 
3099   assert(p != (unsigned char *) NULL);
3100   q=p+length;
3101   while (p < q)
3102   {
3103     c=(int) (*p);
3104     *p=(*(p+1));
3105     p++;
3106     *p++=(unsigned char) c;
3107   }
3108 }
3109 
3110 /*
3111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3112 %                                                                             %
3113 %                                                                             %
3114 %                                                                             %
3115 +   O p e n B l o b                                                           %
3116 %                                                                             %
3117 %                                                                             %
3118 %                                                                             %
3119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3120 %
3121 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
3122 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
3123 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
3124 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
3125 %  from a system command.
3126 %
3127 %  The format of the OpenBlob method is:
3128 %
3129 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
3130 %        const BlobMode mode,ExceptionInfo *exception)
3131 %
3132 %  A description of each parameter follows:
3133 %
3134 %    o image_info: the image info.
3135 %
3136 %    o image: the image.
3137 %
3138 %    o mode: the mode for opening the file.
3139 %
3140 */
3141 
SetStreamBuffering(const ImageInfo * image_info,Image * image)3142 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
3143   Image *image)
3144 {
3145   const char
3146     *option;
3147 
3148   int
3149     status;
3150 
3151   size_t
3152     size;
3153 
3154   size=16384;
3155   option=GetImageOption(image_info,"stream:buffer-size");
3156   if (option != (const char *) NULL)
3157     size=StringToUnsignedLong(option);
3158   status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
3159     _IONBF : _IOFBF,size);
3160   return(status == 0 ? MagickTrue : MagickFalse);
3161 }
3162 
OpenBlob(const ImageInfo * image_info,Image * image,const BlobMode mode,ExceptionInfo * exception)3163 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
3164   Image *image,const BlobMode mode,ExceptionInfo *exception)
3165 {
3166   BlobInfo
3167     *magick_restrict blob_info;
3168 
3169   char
3170     extension[MagickPathExtent],
3171     filename[MagickPathExtent];
3172 
3173   const char
3174     *type;
3175 
3176   MagickBooleanType
3177     status;
3178 
3179   PolicyRights
3180     rights;
3181 
3182   assert(image_info != (ImageInfo *) NULL);
3183   assert(image_info->signature == MagickCoreSignature);
3184   if (image_info->debug != MagickFalse)
3185     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3186       image_info->filename);
3187   assert(image != (Image *) NULL);
3188   assert(image->signature == MagickCoreSignature);
3189   blob_info=image->blob;
3190   if (image_info->blob != (void *) NULL)
3191     {
3192       if (image_info->stream != (StreamHandler) NULL)
3193         blob_info->stream=(StreamHandler) image_info->stream;
3194       AttachBlob(blob_info,image_info->blob,image_info->length);
3195       return(MagickTrue);
3196     }
3197   if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3198       (*image->filename == '\0'))
3199     {
3200       blob_info->type=CustomStream;
3201       blob_info->custom_stream=image_info->custom_stream;
3202       return(MagickTrue);
3203     }
3204   (void) DetachBlob(blob_info);
3205   blob_info->mode=mode;
3206   switch (mode)
3207   {
3208     default: type="r"; break;
3209     case ReadBlobMode: type="r"; break;
3210     case ReadBinaryBlobMode: type="rb"; break;
3211     case WriteBlobMode: type="w"; break;
3212     case WriteBinaryBlobMode: type="w+b"; break;
3213     case AppendBlobMode: type="a"; break;
3214     case AppendBinaryBlobMode: type="a+b"; break;
3215   }
3216   if (*type != 'r')
3217     blob_info->synchronize=image_info->synchronize;
3218   if (image_info->stream != (StreamHandler) NULL)
3219     {
3220       blob_info->stream=image_info->stream;
3221       if (*type == 'w')
3222         {
3223           blob_info->type=FifoStream;
3224           return(MagickTrue);
3225         }
3226     }
3227   /*
3228     Open image file.
3229   */
3230   *filename='\0';
3231   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3232   rights=ReadPolicyRights;
3233   if (*type == 'w')
3234     rights=WritePolicyRights;
3235   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
3236     {
3237       errno=EPERM;
3238       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
3239         "NotAuthorized","`%s'",filename);
3240       return(MagickFalse);
3241     }
3242   if ((LocaleCompare(filename,"-") == 0) ||
3243       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3244     {
3245       blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3246 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3247       if (strchr(type,'b') != (char *) NULL)
3248         setmode(fileno(blob_info->file_info.file),_O_BINARY);
3249 #endif
3250       blob_info->type=StandardStream;
3251       blob_info->exempt=MagickTrue;
3252       return(SetStreamBuffering(image_info,image));
3253     }
3254   if ((LocaleNCompare(filename,"fd:",3) == 0) &&
3255       (IsGeometry(filename+3) != MagickFalse))
3256     {
3257       char
3258         fileMode[MagickPathExtent];
3259 
3260       *fileMode =(*type);
3261       fileMode[1]='\0';
3262       blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
3263       if (blob_info->file_info.file == (FILE *) NULL)
3264         {
3265           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3266           return(MagickFalse);
3267         }
3268 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3269       if (strchr(type,'b') != (char *) NULL)
3270         setmode(fileno(blob_info->file_info.file),_O_BINARY);
3271 #endif
3272       blob_info->type=FileStream;
3273       blob_info->exempt=MagickTrue;
3274       return(SetStreamBuffering(image_info,image));
3275     }
3276 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3277   if (*filename == '|')
3278     {
3279       char
3280         fileMode[MagickPathExtent],
3281         *sanitize_command;
3282 
3283       /*
3284         Pipe image to or from a system command.
3285       */
3286 #if defined(SIGPIPE)
3287       if (*type == 'w')
3288         (void) signal(SIGPIPE,SIG_IGN);
3289 #endif
3290       *fileMode =(*type);
3291       fileMode[1]='\0';
3292       sanitize_command=SanitizeString(filename+1);
3293       blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3294       sanitize_command=DestroyString(sanitize_command);
3295       if (blob_info->file_info.file == (FILE *) NULL)
3296         {
3297           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3298           return(MagickFalse);
3299         }
3300       blob_info->type=PipeStream;
3301       blob_info->exempt=MagickTrue;
3302       return(SetStreamBuffering(image_info,image));
3303     }
3304 #endif
3305   status=GetPathAttributes(filename,&blob_info->properties);
3306 #if defined(S_ISFIFO)
3307   if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3308     {
3309       blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3310       if (blob_info->file_info.file == (FILE *) NULL)
3311         {
3312           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3313           return(MagickFalse);
3314         }
3315       blob_info->type=FileStream;
3316       blob_info->exempt=MagickTrue;
3317       return(SetStreamBuffering(image_info,image));
3318     }
3319 #endif
3320   GetPathComponent(image->filename,ExtensionPath,extension);
3321   if (*type == 'w')
3322     {
3323       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3324       if ((image_info->adjoin == MagickFalse) ||
3325           (strchr(filename,'%') != (char *) NULL))
3326         {
3327           /*
3328             Form filename for multi-part images.
3329           */
3330           (void) InterpretImageFilename(image_info,image,image->filename,(int)
3331             image->scene,filename,exception);
3332           if ((LocaleCompare(filename,image->filename) == 0) &&
3333               ((GetPreviousImageInList(image) != (Image *) NULL) ||
3334                (GetNextImageInList(image) != (Image *) NULL)))
3335             {
3336               char
3337                 path[MagickPathExtent];
3338 
3339               GetPathComponent(image->filename,RootPath,path);
3340               if (*extension == '\0')
3341                 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
3342                   path,(double) image->scene);
3343               else
3344                 (void) FormatLocaleString(filename,MagickPathExtent,
3345                   "%s-%.20g.%s",path,(double) image->scene,extension);
3346             }
3347           (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3348 #if defined(macintosh)
3349           SetApplicationType(filename,image_info->magick,'8BIM');
3350 #endif
3351         }
3352     }
3353   if (image_info->file != (FILE *) NULL)
3354     {
3355       blob_info->file_info.file=image_info->file;
3356       blob_info->type=FileStream;
3357       blob_info->exempt=MagickTrue;
3358     }
3359   else
3360     if (*type == 'r')
3361       {
3362         blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3363         if (blob_info->file_info.file != (FILE *) NULL)
3364           {
3365             size_t
3366               count;
3367 
3368             unsigned char
3369               magick[3];
3370 
3371             blob_info->type=FileStream;
3372             (void) SetStreamBuffering(image_info,image);
3373             (void) memset(magick,0,sizeof(magick));
3374             count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3375             (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3376 #if defined(MAGICKCORE_POSIX_SUPPORT)
3377             (void) fflush(blob_info->file_info.file);
3378 #endif
3379             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
3380                "  read %.20g magic header bytes",(double) count);
3381 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3382             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3383                 ((int) magick[2] == 0x08))
3384               {
3385                 if (blob_info->file_info.file != (FILE *) NULL)
3386                   (void) fclose(blob_info->file_info.file);
3387                 blob_info->file_info.file=(FILE *) NULL;
3388                 blob_info->file_info.gzfile=gzopen(filename,"rb");
3389                 if (blob_info->file_info.gzfile != (gzFile) NULL)
3390                   blob_info->type=ZipStream;
3391                }
3392 #endif
3393 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3394             if (strncmp((char *) magick,"BZh",3) == 0)
3395               {
3396                 if (blob_info->file_info.file != (FILE *) NULL)
3397                   (void) fclose(blob_info->file_info.file);
3398                 blob_info->file_info.file=(FILE *) NULL;
3399                 blob_info->file_info.bzfile=BZ2_bzopen(filename,"r");
3400                 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3401                   blob_info->type=BZipStream;
3402               }
3403 #endif
3404             if (blob_info->type == FileStream)
3405               {
3406                 const MagickInfo
3407                   *magick_info;
3408 
3409                 ExceptionInfo
3410                   *sans_exception;
3411 
3412                 size_t
3413                   length;
3414 
3415                 sans_exception=AcquireExceptionInfo();
3416                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3417                 sans_exception=DestroyExceptionInfo(sans_exception);
3418                 length=(size_t) blob_info->properties.st_size;
3419                 if ((magick_info != (const MagickInfo *) NULL) &&
3420                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3421                     (length > MagickMaxBufferExtent) &&
3422                     (AcquireMagickResource(MapResource,length) != MagickFalse))
3423                   {
3424                     void
3425                       *blob;
3426 
3427                     blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3428                       length);
3429                     if (blob == (void *) NULL)
3430                       RelinquishMagickResource(MapResource,length);
3431                     else
3432                       {
3433                         /*
3434                           Format supports blobs-- use memory-mapped I/O.
3435                         */
3436                         if (image_info->file != (FILE *) NULL)
3437                           blob_info->exempt=MagickFalse;
3438                         else
3439                           {
3440                             (void) fclose(blob_info->file_info.file);
3441                             blob_info->file_info.file=(FILE *) NULL;
3442                           }
3443                         AttachBlob(blob_info,blob,length);
3444                         blob_info->mapped=MagickTrue;
3445                       }
3446                   }
3447               }
3448           }
3449         }
3450       else
3451 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3452         if ((LocaleCompare(extension,"Z") == 0) ||
3453             (LocaleCompare(extension,"gz") == 0) ||
3454             (LocaleCompare(extension,"wmz") == 0) ||
3455             (LocaleCompare(extension,"svgz") == 0))
3456           {
3457             blob_info->file_info.gzfile=gzopen(filename,"wb");
3458             if (blob_info->file_info.gzfile != (gzFile) NULL)
3459               blob_info->type=ZipStream;
3460           }
3461         else
3462 #endif
3463 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3464           if (LocaleCompare(extension,"bz2") == 0)
3465             {
3466               blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
3467               if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3468                 blob_info->type=BZipStream;
3469             }
3470           else
3471 #endif
3472             {
3473               blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3474               if (blob_info->file_info.file != (FILE *) NULL)
3475                 {
3476                   blob_info->type=FileStream;
3477                   (void) SetStreamBuffering(image_info,image);
3478                 }
3479        }
3480   blob_info->status=MagickFalse;
3481   if (blob_info->type != UndefinedStream)
3482     blob_info->size=GetBlobSize(image);
3483   else
3484     {
3485       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3486       return(MagickFalse);
3487     }
3488   return(MagickTrue);
3489 }
3490 
3491 /*
3492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3493 %                                                                             %
3494 %                                                                             %
3495 %                                                                             %
3496 +   P i n g B l o b                                                           %
3497 %                                                                             %
3498 %                                                                             %
3499 %                                                                             %
3500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3501 %
3502 %  PingBlob() returns all the attributes of an image or image sequence except
3503 %  for the pixels.  It is much faster and consumes far less memory than
3504 %  BlobToImage().  On failure, a NULL image is returned and exception
3505 %  describes the reason for the failure.
3506 %
3507 %  The format of the PingBlob method is:
3508 %
3509 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
3510 %        const size_t length,ExceptionInfo *exception)
3511 %
3512 %  A description of each parameter follows:
3513 %
3514 %    o image_info: the image info.
3515 %
3516 %    o blob: the address of a character stream in one of the image formats
3517 %      understood by ImageMagick.
3518 %
3519 %    o length: This size_t integer reflects the length in bytes of the blob.
3520 %
3521 %    o exception: return any errors or warnings in this structure.
3522 %
3523 */
3524 
3525 #if defined(__cplusplus) || defined(c_plusplus)
3526 extern "C" {
3527 #endif
3528 
PingStream(const Image * magick_unused (image),const void * magick_unused (pixels),const size_t columns)3529 static size_t PingStream(const Image *magick_unused(image),
3530   const void *magick_unused(pixels),const size_t columns)
3531 {
3532   magick_unreferenced(image);
3533   magick_unreferenced(pixels);
3534   return(columns);
3535 }
3536 
3537 #if defined(__cplusplus) || defined(c_plusplus)
3538 }
3539 #endif
3540 
PingBlob(const ImageInfo * image_info,const void * blob,const size_t length,ExceptionInfo * exception)3541 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3542   const size_t length,ExceptionInfo *exception)
3543 {
3544   const MagickInfo
3545     *magick_info;
3546 
3547   Image
3548     *image;
3549 
3550   ImageInfo
3551     *clone_info,
3552     *ping_info;
3553 
3554   MagickBooleanType
3555     status;
3556 
3557   assert(image_info != (ImageInfo *) NULL);
3558   assert(image_info->signature == MagickCoreSignature);
3559   if (image_info->debug != MagickFalse)
3560     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3561       image_info->filename);
3562   assert(exception != (ExceptionInfo *) NULL);
3563   if ((blob == (const void *) NULL) || (length == 0))
3564     {
3565       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3566         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3567       return((Image *) NULL);
3568     }
3569   ping_info=CloneImageInfo(image_info);
3570   ping_info->blob=(void *) blob;
3571   ping_info->length=length;
3572   ping_info->ping=MagickTrue;
3573   if (*ping_info->magick == '\0')
3574     (void) SetImageInfo(ping_info,0,exception);
3575   magick_info=GetMagickInfo(ping_info->magick,exception);
3576   if (magick_info == (const MagickInfo *) NULL)
3577     {
3578       (void) ThrowMagickException(exception,GetMagickModule(),
3579         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3580         ping_info->magick);
3581       ping_info=DestroyImageInfo(ping_info);
3582       return((Image *) NULL);
3583     }
3584   if (GetMagickBlobSupport(magick_info) != MagickFalse)
3585     {
3586       char
3587         filename[MagickPathExtent];
3588 
3589       /*
3590         Native blob support for this image format.
3591       */
3592       (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3593       (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3594         ping_info->magick,filename);
3595       image=ReadStream(ping_info,&PingStream,exception);
3596       if (image != (Image *) NULL)
3597         (void) DetachBlob(image->blob);
3598       ping_info=DestroyImageInfo(ping_info);
3599       return(image);
3600     }
3601   /*
3602     Write blob to a temporary file on disk.
3603   */
3604   ping_info->blob=(void *) NULL;
3605   ping_info->length=0;
3606   *ping_info->filename='\0';
3607   status=BlobToFile(ping_info->filename,blob,length,exception);
3608   if (status == MagickFalse)
3609     {
3610       (void) RelinquishUniqueFileResource(ping_info->filename);
3611       ping_info=DestroyImageInfo(ping_info);
3612       return((Image *) NULL);
3613     }
3614   clone_info=CloneImageInfo(ping_info);
3615   (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3616     ping_info->magick,ping_info->filename);
3617   image=ReadStream(clone_info,&PingStream,exception);
3618   if (image != (Image *) NULL)
3619     {
3620       Image
3621         *images;
3622 
3623       /*
3624         Restore original filenames and image format.
3625       */
3626       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3627       {
3628         (void) CopyMagickString(images->filename,image_info->filename,
3629           MagickPathExtent);
3630         (void) CopyMagickString(images->magick_filename,image_info->filename,
3631           MagickPathExtent);
3632         (void) CopyMagickString(images->magick,magick_info->name,
3633           MagickPathExtent);
3634         images=GetNextImageInList(images);
3635       }
3636     }
3637   clone_info=DestroyImageInfo(clone_info);
3638   (void) RelinquishUniqueFileResource(ping_info->filename);
3639   ping_info=DestroyImageInfo(ping_info);
3640   return(image);
3641 }
3642 
3643 /*
3644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3645 %                                                                             %
3646 %                                                                             %
3647 %                                                                             %
3648 +  R e a d B l o b                                                            %
3649 %                                                                             %
3650 %                                                                             %
3651 %                                                                             %
3652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3653 %
3654 %  ReadBlob() reads data from the blob or image file and returns it.  It
3655 %  returns the number of bytes read. If length is zero, ReadBlob() returns
3656 %  zero and has no other results. If length is greater than SSIZE_MAX, the
3657 %  result is unspecified.
3658 %
3659 %  The format of the ReadBlob method is:
3660 %
3661 %      ssize_t ReadBlob(Image *image,const size_t length,void *data)
3662 %
3663 %  A description of each parameter follows:
3664 %
3665 %    o image: the image.
3666 %
3667 %    o length:  Specifies an integer representing the number of bytes to read
3668 %      from the file.
3669 %
3670 %    o data:  Specifies an area to place the information requested from the
3671 %      file.
3672 %
3673 */
ReadBlob(Image * image,const size_t length,void * data)3674 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3675 {
3676   BlobInfo
3677     *magick_restrict blob_info;
3678 
3679   int
3680     c;
3681 
3682   register unsigned char
3683     *q;
3684 
3685   ssize_t
3686     count;
3687 
3688   assert(image != (Image *) NULL);
3689   assert(image->signature == MagickCoreSignature);
3690   assert(image->blob != (BlobInfo *) NULL);
3691   assert(image->blob->type != UndefinedStream);
3692   if (length == 0)
3693     return(0);
3694   assert(data != (void *) NULL);
3695   blob_info=image->blob;
3696   count=0;
3697   q=(unsigned char *) data;
3698   switch (blob_info->type)
3699   {
3700     case UndefinedStream:
3701       break;
3702     case StandardStream:
3703     case FileStream:
3704     case PipeStream:
3705     {
3706       switch (length)
3707       {
3708         default:
3709         {
3710           count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3711           break;
3712         }
3713         case 4:
3714         {
3715           c=getc(blob_info->file_info.file);
3716           if (c == EOF)
3717             break;
3718           *q++=(unsigned char) c;
3719           count++;
3720         }
3721         case 3:
3722         {
3723           c=getc(blob_info->file_info.file);
3724           if (c == EOF)
3725             break;
3726           *q++=(unsigned char) c;
3727           count++;
3728         }
3729         case 2:
3730         {
3731           c=getc(blob_info->file_info.file);
3732           if (c == EOF)
3733             break;
3734           *q++=(unsigned char) c;
3735           count++;
3736         }
3737         case 1:
3738         {
3739           c=getc(blob_info->file_info.file);
3740           if (c == EOF)
3741             break;
3742           *q++=(unsigned char) c;
3743           count++;
3744         }
3745         case 0:
3746           break;
3747       }
3748       break;
3749     }
3750     case ZipStream:
3751     {
3752 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3753       switch (length)
3754       {
3755         default:
3756         {
3757           register ssize_t
3758             i;
3759 
3760           for (i=0; i < (ssize_t) length; i+=count)
3761           {
3762             count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3763               (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3764             if (count <= 0)
3765               {
3766                 count=0;
3767                 if (errno != EINTR)
3768                   break;
3769               }
3770           }
3771           count=i;
3772           break;
3773         }
3774         case 4:
3775         {
3776           c=gzgetc(blob_info->file_info.gzfile);
3777           if (c == EOF)
3778             break;
3779           *q++=(unsigned char) c;
3780           count++;
3781         }
3782         case 3:
3783         {
3784           c=gzgetc(blob_info->file_info.gzfile);
3785           if (c == EOF)
3786             break;
3787           *q++=(unsigned char) c;
3788           count++;
3789         }
3790         case 2:
3791         {
3792           c=gzgetc(blob_info->file_info.gzfile);
3793           if (c == EOF)
3794             break;
3795           *q++=(unsigned char) c;
3796           count++;
3797         }
3798         case 1:
3799         {
3800           c=gzgetc(blob_info->file_info.gzfile);
3801           if (c == EOF)
3802             break;
3803           *q++=(unsigned char) c;
3804           count++;
3805         }
3806         case 0:
3807           break;
3808       }
3809 #endif
3810       break;
3811     }
3812     case BZipStream:
3813     {
3814 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3815       register ssize_t
3816         i;
3817 
3818       for (i=0; i < (ssize_t) length; i+=count)
3819       {
3820         count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
3821           (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3822         if (count <= 0)
3823           {
3824             count=0;
3825             if (errno != EINTR)
3826               break;
3827           }
3828       }
3829       count=i;
3830 #endif
3831       break;
3832     }
3833     case FifoStream:
3834       break;
3835     case BlobStream:
3836     {
3837       register const unsigned char
3838         *p;
3839 
3840       if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3841         {
3842           blob_info->eof=MagickTrue;
3843           break;
3844         }
3845       p=blob_info->data+blob_info->offset;
3846       count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3847         blob_info->length-blob_info->offset);
3848       blob_info->offset+=count;
3849       if (count != (ssize_t) length)
3850         blob_info->eof=MagickTrue;
3851       (void) memcpy(q,p,(size_t) count);
3852       break;
3853     }
3854     case CustomStream:
3855     {
3856       if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
3857         count=blob_info->custom_stream->reader(q,length,
3858           blob_info->custom_stream->data);
3859       break;
3860     }
3861   }
3862   return(count);
3863 }
3864 
3865 /*
3866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3867 %                                                                             %
3868 %                                                                             %
3869 %                                                                             %
3870 +  R e a d B l o b B y t e                                                    %
3871 %                                                                             %
3872 %                                                                             %
3873 %                                                                             %
3874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3875 %
3876 %  ReadBlobByte() reads a single byte from the image file and returns it.
3877 %
3878 %  The format of the ReadBlobByte method is:
3879 %
3880 %      int ReadBlobByte(Image *image)
3881 %
3882 %  A description of each parameter follows.
3883 %
3884 %    o image: the image.
3885 %
3886 */
ReadBlobByte(Image * image)3887 MagickExport int ReadBlobByte(Image *image)
3888 {
3889   BlobInfo
3890     *magick_restrict blob_info;
3891 
3892   register const unsigned char
3893     *p;
3894 
3895   unsigned char
3896     buffer[1];
3897 
3898   assert(image != (Image *) NULL);
3899   assert(image->signature == MagickCoreSignature);
3900   assert(image->blob != (BlobInfo *) NULL);
3901   assert(image->blob->type != UndefinedStream);
3902   blob_info=image->blob;
3903   switch (blob_info->type)
3904   {
3905     case StandardStream:
3906     case FileStream:
3907     case PipeStream:
3908     {
3909       int
3910         c;
3911 
3912       p=(const unsigned char *) buffer;
3913       c=getc(blob_info->file_info.file);
3914       if (c == EOF)
3915         return(EOF);
3916       *buffer=(unsigned char) c;
3917       break;
3918     }
3919     default:
3920     {
3921       ssize_t
3922         count;
3923 
3924       p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3925       if (count != 1)
3926         return(EOF);
3927       break;
3928     }
3929   }
3930   return((int) (*p));
3931 }
3932 
3933 /*
3934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3935 %                                                                             %
3936 %                                                                             %
3937 %                                                                             %
3938 +  R e a d B l o b D o u b l e                                                %
3939 %                                                                             %
3940 %                                                                             %
3941 %                                                                             %
3942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3943 %
3944 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3945 %  specified by the endian member of the image structure.
3946 %
3947 %  The format of the ReadBlobDouble method is:
3948 %
3949 %      double ReadBlobDouble(Image *image)
3950 %
3951 %  A description of each parameter follows.
3952 %
3953 %    o image: the image.
3954 %
3955 */
ReadBlobDouble(Image * image)3956 MagickExport double ReadBlobDouble(Image *image)
3957 {
3958   union
3959   {
3960     MagickSizeType
3961       unsigned_value;
3962 
3963     double
3964       double_value;
3965   } quantum;
3966 
3967   quantum.double_value=0.0;
3968   quantum.unsigned_value=ReadBlobLongLong(image);
3969   return(quantum.double_value);
3970 }
3971 
3972 /*
3973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3974 %                                                                             %
3975 %                                                                             %
3976 %                                                                             %
3977 +  R e a d B l o b F l o a t                                                  %
3978 %                                                                             %
3979 %                                                                             %
3980 %                                                                             %
3981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3982 %
3983 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3984 %  specified by the endian member of the image structure.
3985 %
3986 %  The format of the ReadBlobFloat method is:
3987 %
3988 %      float ReadBlobFloat(Image *image)
3989 %
3990 %  A description of each parameter follows.
3991 %
3992 %    o image: the image.
3993 %
3994 */
ReadBlobFloat(Image * image)3995 MagickExport float ReadBlobFloat(Image *image)
3996 {
3997   union
3998   {
3999     unsigned int
4000       unsigned_value;
4001 
4002     float
4003       float_value;
4004   } quantum;
4005 
4006   quantum.float_value=0.0;
4007   quantum.unsigned_value=ReadBlobLong(image);
4008   return(quantum.float_value);
4009 }
4010 
4011 /*
4012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4013 %                                                                             %
4014 %                                                                             %
4015 %                                                                             %
4016 +  R e a d B l o b L o n g                                                    %
4017 %                                                                             %
4018 %                                                                             %
4019 %                                                                             %
4020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4021 %
4022 %  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
4023 %  byte-order specified by the endian member of the image structure.
4024 %
4025 %  The format of the ReadBlobLong method is:
4026 %
4027 %      unsigned int ReadBlobLong(Image *image)
4028 %
4029 %  A description of each parameter follows.
4030 %
4031 %    o image: the image.
4032 %
4033 */
ReadBlobLong(Image * image)4034 MagickExport unsigned int ReadBlobLong(Image *image)
4035 {
4036   register const unsigned char
4037     *p;
4038 
4039   ssize_t
4040     count;
4041 
4042   unsigned char
4043     buffer[4];
4044 
4045   unsigned int
4046     value;
4047 
4048   assert(image != (Image *) NULL);
4049   assert(image->signature == MagickCoreSignature);
4050   *buffer='\0';
4051   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4052   if (count != 4)
4053     return(0UL);
4054   if (image->endian == LSBEndian)
4055     {
4056       value=(unsigned int) (*p++);
4057       value|=(unsigned int) (*p++) << 8;
4058       value|=(unsigned int) (*p++) << 16;
4059       value|=(unsigned int) (*p++) << 24;
4060       return(value);
4061     }
4062   value=(unsigned int) (*p++) << 24;
4063   value|=(unsigned int) (*p++) << 16;
4064   value|=(unsigned int) (*p++) << 8;
4065   value|=(unsigned int) (*p++);
4066   return(value);
4067 }
4068 
4069 /*
4070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4071 %                                                                             %
4072 %                                                                             %
4073 %                                                                             %
4074 +  R e a d B l o b L o n g L o n g                                            %
4075 %                                                                             %
4076 %                                                                             %
4077 %                                                                             %
4078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4079 %
4080 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
4081 %  byte-order specified by the endian member of the image structure.
4082 %
4083 %  The format of the ReadBlobLongLong method is:
4084 %
4085 %      MagickSizeType ReadBlobLongLong(Image *image)
4086 %
4087 %  A description of each parameter follows.
4088 %
4089 %    o image: the image.
4090 %
4091 */
ReadBlobLongLong(Image * image)4092 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
4093 {
4094   MagickSizeType
4095     value;
4096 
4097   register const unsigned char
4098     *p;
4099 
4100   ssize_t
4101     count;
4102 
4103   unsigned char
4104     buffer[8];
4105 
4106   assert(image != (Image *) NULL);
4107   assert(image->signature == MagickCoreSignature);
4108   *buffer='\0';
4109   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4110   if (count != 8)
4111     return(MagickULLConstant(0));
4112   if (image->endian == LSBEndian)
4113     {
4114       value=(MagickSizeType) (*p++);
4115       value|=(MagickSizeType) (*p++) << 8;
4116       value|=(MagickSizeType) (*p++) << 16;
4117       value|=(MagickSizeType) (*p++) << 24;
4118       value|=(MagickSizeType) (*p++) << 32;
4119       value|=(MagickSizeType) (*p++) << 40;
4120       value|=(MagickSizeType) (*p++) << 48;
4121       value|=(MagickSizeType) (*p++) << 56;
4122       return(value);
4123     }
4124   value=(MagickSizeType) (*p++) << 56;
4125   value|=(MagickSizeType) (*p++) << 48;
4126   value|=(MagickSizeType) (*p++) << 40;
4127   value|=(MagickSizeType) (*p++) << 32;
4128   value|=(MagickSizeType) (*p++) << 24;
4129   value|=(MagickSizeType) (*p++) << 16;
4130   value|=(MagickSizeType) (*p++) << 8;
4131   value|=(MagickSizeType) (*p++);
4132   return(value);
4133 }
4134 
4135 /*
4136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4137 %                                                                             %
4138 %                                                                             %
4139 %                                                                             %
4140 +  R e a d B l o b S h o r t                                                  %
4141 %                                                                             %
4142 %                                                                             %
4143 %                                                                             %
4144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4145 %
4146 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
4147 %  specified by the endian member of the image structure.
4148 %
4149 %  The format of the ReadBlobShort method is:
4150 %
4151 %      unsigned short ReadBlobShort(Image *image)
4152 %
4153 %  A description of each parameter follows.
4154 %
4155 %    o image: the image.
4156 %
4157 */
ReadBlobShort(Image * image)4158 MagickExport unsigned short ReadBlobShort(Image *image)
4159 {
4160   register const unsigned char
4161     *p;
4162 
4163   register unsigned short
4164     value;
4165 
4166   ssize_t
4167     count;
4168 
4169   unsigned char
4170     buffer[2];
4171 
4172   assert(image != (Image *) NULL);
4173   assert(image->signature == MagickCoreSignature);
4174   *buffer='\0';
4175   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4176   if (count != 2)
4177     return((unsigned short) 0U);
4178   if (image->endian == LSBEndian)
4179     {
4180       value=(unsigned short) (*p++);
4181       value|=(unsigned short) (*p++) << 8;
4182       return(value);
4183     }
4184   value=(unsigned short) ((unsigned short) (*p++) << 8);
4185   value|=(unsigned short) (*p++);
4186   return(value);
4187 }
4188 
4189 /*
4190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4191 %                                                                             %
4192 %                                                                             %
4193 %                                                                             %
4194 +  R e a d B l o b L S B L o n g                                              %
4195 %                                                                             %
4196 %                                                                             %
4197 %                                                                             %
4198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4199 %
4200 %  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
4201 %  least-significant byte first order.
4202 %
4203 %  The format of the ReadBlobLSBLong method is:
4204 %
4205 %      unsigned int ReadBlobLSBLong(Image *image)
4206 %
4207 %  A description of each parameter follows.
4208 %
4209 %    o image: the image.
4210 %
4211 */
ReadBlobLSBLong(Image * image)4212 MagickExport unsigned int ReadBlobLSBLong(Image *image)
4213 {
4214   register const unsigned char
4215     *p;
4216 
4217   register unsigned int
4218     value;
4219 
4220   ssize_t
4221     count;
4222 
4223   unsigned char
4224     buffer[4];
4225 
4226   assert(image != (Image *) NULL);
4227   assert(image->signature == MagickCoreSignature);
4228   *buffer='\0';
4229   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4230   if (count != 4)
4231     return(0U);
4232   value=(unsigned int) (*p++);
4233   value|=(unsigned int) (*p++) << 8;
4234   value|=(unsigned int) (*p++) << 16;
4235   value|=(unsigned int) (*p++) << 24;
4236   return(value);
4237 }
4238 
4239 /*
4240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4241 %                                                                             %
4242 %                                                                             %
4243 %                                                                             %
4244 +  R e a d B l o b L S B S i g n e d L o n g                                  %
4245 %                                                                             %
4246 %                                                                             %
4247 %                                                                             %
4248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4249 %
4250 %  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
4251 %  least-significant byte first order.
4252 %
4253 %  The format of the ReadBlobLSBSignedLong method is:
4254 %
4255 %      signed int ReadBlobLSBSignedLong(Image *image)
4256 %
4257 %  A description of each parameter follows.
4258 %
4259 %    o image: the image.
4260 %
4261 */
ReadBlobLSBSignedLong(Image * image)4262 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
4263 {
4264   union
4265   {
4266     unsigned int
4267       unsigned_value;
4268 
4269     signed int
4270       signed_value;
4271   } quantum;
4272 
4273   quantum.unsigned_value=ReadBlobLSBLong(image);
4274   return(quantum.signed_value);
4275 }
4276 
4277 /*
4278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4279 %                                                                             %
4280 %                                                                             %
4281 %                                                                             %
4282 +  R e a d B l o b L S B S h o r t                                            %
4283 %                                                                             %
4284 %                                                                             %
4285 %                                                                             %
4286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4287 %
4288 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4289 %  least-significant byte first order.
4290 %
4291 %  The format of the ReadBlobLSBShort method is:
4292 %
4293 %      unsigned short ReadBlobLSBShort(Image *image)
4294 %
4295 %  A description of each parameter follows.
4296 %
4297 %    o image: the image.
4298 %
4299 */
ReadBlobLSBShort(Image * image)4300 MagickExport unsigned short ReadBlobLSBShort(Image *image)
4301 {
4302   register const unsigned char
4303     *p;
4304 
4305   register unsigned short
4306     value;
4307 
4308   ssize_t
4309     count;
4310 
4311   unsigned char
4312     buffer[2];
4313 
4314   assert(image != (Image *) NULL);
4315   assert(image->signature == MagickCoreSignature);
4316   *buffer='\0';
4317   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4318   if (count != 2)
4319     return((unsigned short) 0U);
4320   value=(unsigned short) (*p++);
4321   value|=(unsigned short) (*p++) << 8;
4322   return(value);
4323 }
4324 
4325 /*
4326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4327 %                                                                             %
4328 %                                                                             %
4329 %                                                                             %
4330 +  R e a d B l o b L S B S i g n e d S h o r t                                %
4331 %                                                                             %
4332 %                                                                             %
4333 %                                                                             %
4334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4335 %
4336 %  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4337 %  least-significant byte-order.
4338 %
4339 %  The format of the ReadBlobLSBSignedShort method is:
4340 %
4341 %      signed short ReadBlobLSBSignedShort(Image *image)
4342 %
4343 %  A description of each parameter follows.
4344 %
4345 %    o image: the image.
4346 %
4347 */
ReadBlobLSBSignedShort(Image * image)4348 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
4349 {
4350   union
4351   {
4352     unsigned short
4353       unsigned_value;
4354 
4355     signed short
4356       signed_value;
4357   } quantum;
4358 
4359   quantum.unsigned_value=ReadBlobLSBShort(image);
4360   return(quantum.signed_value);
4361 }
4362 
4363 /*
4364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4365 %                                                                             %
4366 %                                                                             %
4367 %                                                                             %
4368 +  R e a d B l o b M S B L o n g                                              %
4369 %                                                                             %
4370 %                                                                             %
4371 %                                                                             %
4372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4373 %
4374 %  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4375 %  most-significant byte first order.
4376 %
4377 %  The format of the ReadBlobMSBLong method is:
4378 %
4379 %      unsigned int ReadBlobMSBLong(Image *image)
4380 %
4381 %  A description of each parameter follows.
4382 %
4383 %    o image: the image.
4384 %
4385 */
ReadBlobMSBLong(Image * image)4386 MagickExport unsigned int ReadBlobMSBLong(Image *image)
4387 {
4388   register const unsigned char
4389     *p;
4390 
4391   register unsigned int
4392     value;
4393 
4394   ssize_t
4395     count;
4396 
4397   unsigned char
4398     buffer[4];
4399 
4400   assert(image != (Image *) NULL);
4401   assert(image->signature == MagickCoreSignature);
4402   *buffer='\0';
4403   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4404   if (count != 4)
4405     return(0UL);
4406   value=(unsigned int) (*p++) << 24;
4407   value|=(unsigned int) (*p++) << 16;
4408   value|=(unsigned int) (*p++) << 8;
4409   value|=(unsigned int) (*p++);
4410   return(value);
4411 }
4412 
4413 /*
4414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4415 %                                                                             %
4416 %                                                                             %
4417 %                                                                             %
4418 +  R e a d B l o b M S B L o n g L o n g                                      %
4419 %                                                                             %
4420 %                                                                             %
4421 %                                                                             %
4422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4423 %
4424 %  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4425 %  in most-significant byte first order.
4426 %
4427 %  The format of the ReadBlobMSBLongLong method is:
4428 %
4429 %      unsigned int ReadBlobMSBLongLong(Image *image)
4430 %
4431 %  A description of each parameter follows.
4432 %
4433 %    o image: the image.
4434 %
4435 */
ReadBlobMSBLongLong(Image * image)4436 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
4437 {
4438   register const unsigned char
4439     *p;
4440 
4441   register MagickSizeType
4442     value;
4443 
4444   ssize_t
4445     count;
4446 
4447   unsigned char
4448     buffer[8];
4449 
4450   assert(image != (Image *) NULL);
4451   assert(image->signature == MagickCoreSignature);
4452   *buffer='\0';
4453   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4454   if (count != 8)
4455     return(MagickULLConstant(0));
4456   value=(MagickSizeType) (*p++) << 56;
4457   value|=(MagickSizeType) (*p++) << 48;
4458   value|=(MagickSizeType) (*p++) << 40;
4459   value|=(MagickSizeType) (*p++) << 32;
4460   value|=(MagickSizeType) (*p++) << 24;
4461   value|=(MagickSizeType) (*p++) << 16;
4462   value|=(MagickSizeType) (*p++) << 8;
4463   value|=(MagickSizeType) (*p++);
4464   return(value);
4465 }
4466 
4467 /*
4468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4469 %                                                                             %
4470 %                                                                             %
4471 %                                                                             %
4472 +  R e a d B l o b M S B S h o r t                                            %
4473 %                                                                             %
4474 %                                                                             %
4475 %                                                                             %
4476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4477 %
4478 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4479 %  most-significant byte first order.
4480 %
4481 %  The format of the ReadBlobMSBShort method is:
4482 %
4483 %      unsigned short ReadBlobMSBShort(Image *image)
4484 %
4485 %  A description of each parameter follows.
4486 %
4487 %    o image: the image.
4488 %
4489 */
ReadBlobMSBShort(Image * image)4490 MagickExport unsigned short ReadBlobMSBShort(Image *image)
4491 {
4492   register const unsigned char
4493     *p;
4494 
4495   register unsigned short
4496     value;
4497 
4498   ssize_t
4499     count;
4500 
4501   unsigned char
4502     buffer[2];
4503 
4504   assert(image != (Image *) NULL);
4505   assert(image->signature == MagickCoreSignature);
4506   *buffer='\0';
4507   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4508   if (count != 2)
4509     return((unsigned short) 0U);
4510   value=(unsigned short) ((*p++) << 8);
4511   value|=(unsigned short) (*p++);
4512   return((unsigned short) (value & 0xffff));
4513 }
4514 
4515 /*
4516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4517 %                                                                             %
4518 %                                                                             %
4519 %                                                                             %
4520 +  R e a d B l o b M S B S i g n e d L o n g                                  %
4521 %                                                                             %
4522 %                                                                             %
4523 %                                                                             %
4524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4525 %
4526 %  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4527 %  most-significant byte-order.
4528 %
4529 %  The format of the ReadBlobMSBSignedLong method is:
4530 %
4531 %      signed int ReadBlobMSBSignedLong(Image *image)
4532 %
4533 %  A description of each parameter follows.
4534 %
4535 %    o image: the image.
4536 %
4537 */
ReadBlobMSBSignedLong(Image * image)4538 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4539 {
4540   union
4541   {
4542     unsigned int
4543       unsigned_value;
4544 
4545     signed int
4546       signed_value;
4547   } quantum;
4548 
4549   quantum.unsigned_value=ReadBlobMSBLong(image);
4550   return(quantum.signed_value);
4551 }
4552 
4553 /*
4554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4555 %                                                                             %
4556 %                                                                             %
4557 %                                                                             %
4558 +  R e a d B l o b M S B S i g n e d S h o r t                                %
4559 %                                                                             %
4560 %                                                                             %
4561 %                                                                             %
4562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4563 %
4564 %  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4565 %  most-significant byte-order.
4566 %
4567 %  The format of the ReadBlobMSBSignedShort method is:
4568 %
4569 %      signed short ReadBlobMSBSignedShort(Image *image)
4570 %
4571 %  A description of each parameter follows.
4572 %
4573 %    o image: the image.
4574 %
4575 */
ReadBlobMSBSignedShort(Image * image)4576 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4577 {
4578   union
4579   {
4580     unsigned short
4581       unsigned_value;
4582 
4583     signed short
4584       signed_value;
4585   } quantum;
4586 
4587   quantum.unsigned_value=ReadBlobMSBShort(image);
4588   return(quantum.signed_value);
4589 }
4590 
4591 /*
4592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4593 %                                                                             %
4594 %                                                                             %
4595 %                                                                             %
4596 +  R e a d B l o b S i g n e d L o n g                                        %
4597 %                                                                             %
4598 %                                                                             %
4599 %                                                                             %
4600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4601 %
4602 %  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4603 %  byte-order specified by the endian member of the image structure.
4604 %
4605 %  The format of the ReadBlobSignedLong method is:
4606 %
4607 %      signed int ReadBlobSignedLong(Image *image)
4608 %
4609 %  A description of each parameter follows.
4610 %
4611 %    o image: the image.
4612 %
4613 */
ReadBlobSignedLong(Image * image)4614 MagickExport signed int ReadBlobSignedLong(Image *image)
4615 {
4616   union
4617   {
4618     unsigned int
4619       unsigned_value;
4620 
4621     signed int
4622       signed_value;
4623   } quantum;
4624 
4625   quantum.unsigned_value=ReadBlobLong(image);
4626   return(quantum.signed_value);
4627 }
4628 
4629 /*
4630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4631 %                                                                             %
4632 %                                                                             %
4633 %                                                                             %
4634 +  R e a d B l o b S i g n e d S h o r t                                      %
4635 %                                                                             %
4636 %                                                                             %
4637 %                                                                             %
4638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4639 %
4640 %  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4641 %  byte-order specified by the endian member of the image structure.
4642 %
4643 %  The format of the ReadBlobSignedShort method is:
4644 %
4645 %      signed short ReadBlobSignedShort(Image *image)
4646 %
4647 %  A description of each parameter follows.
4648 %
4649 %    o image: the image.
4650 %
4651 */
ReadBlobSignedShort(Image * image)4652 MagickExport signed short ReadBlobSignedShort(Image *image)
4653 {
4654   union
4655   {
4656     unsigned short
4657       unsigned_value;
4658 
4659     signed short
4660       signed_value;
4661   } quantum;
4662 
4663   quantum.unsigned_value=ReadBlobShort(image);
4664   return(quantum.signed_value);
4665 }
4666 
4667 /*
4668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4669 %                                                                             %
4670 %                                                                             %
4671 %                                                                             %
4672 +  R e a d B l o b S t r e a m                                                %
4673 %                                                                             %
4674 %                                                                             %
4675 %                                                                             %
4676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4677 %
4678 %  ReadBlobStream() reads data from the blob or image file and returns it.  It
4679 %  returns a pointer to the data buffer you supply or to the image memory
4680 %  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4681 %  returns a count of zero and has no other results. If length is greater than
4682 %  SSIZE_MAX, the result is unspecified.
4683 %
4684 %  The format of the ReadBlobStream method is:
4685 %
4686 %      const void *ReadBlobStream(Image *image,const size_t length,void *data,
4687 %        ssize_t *count)
4688 %
4689 %  A description of each parameter follows:
4690 %
4691 %    o image: the image.
4692 %
4693 %    o length:  Specifies an integer representing the number of bytes to read
4694 %      from the file.
4695 %
4696 %    o count: returns the number of bytes read.
4697 %
4698 %    o data:  Specifies an area to place the information requested from the
4699 %      file.
4700 %
4701 */
ReadBlobStream(Image * image,const size_t length,void * data,ssize_t * count)4702 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
4703   void *data,ssize_t *count)
4704 {
4705   BlobInfo
4706     *magick_restrict blob_info;
4707 
4708   assert(image != (Image *) NULL);
4709   assert(image->signature == MagickCoreSignature);
4710   assert(image->blob != (BlobInfo *) NULL);
4711   assert(image->blob->type != UndefinedStream);
4712   assert(count != (ssize_t *) NULL);
4713   blob_info=image->blob;
4714   if (blob_info->type != BlobStream)
4715     {
4716       assert(data != NULL);
4717       *count=ReadBlob(image,length,(unsigned char *) data);
4718       return(data);
4719     }
4720   if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4721     {
4722       *count=0;
4723       blob_info->eof=MagickTrue;
4724       return(data);
4725     }
4726   data=blob_info->data+blob_info->offset;
4727   *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4728     blob_info->length-blob_info->offset);
4729   blob_info->offset+=(*count);
4730   if (*count != (ssize_t) length)
4731     blob_info->eof=MagickTrue;
4732   return(data);
4733 }
4734 
4735 /*
4736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4737 %                                                                             %
4738 %                                                                             %
4739 %                                                                             %
4740 +   R e a d B l o b S t r i n g                                               %
4741 %                                                                             %
4742 %                                                                             %
4743 %                                                                             %
4744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4745 %
4746 %  ReadBlobString() reads characters from a blob or file until a newline
4747 %  character is read or an end-of-file condition is encountered.
4748 %
4749 %  The format of the ReadBlobString method is:
4750 %
4751 %      char *ReadBlobString(Image *image,char *string)
4752 %
4753 %  A description of each parameter follows:
4754 %
4755 %    o image: the image.
4756 %
4757 %    o string: the address of a character buffer.
4758 %
4759 */
ReadBlobString(Image * image,char * string)4760 MagickExport char *ReadBlobString(Image *image,char *string)
4761 {
4762   int
4763     c;
4764 
4765   register ssize_t
4766     i;
4767 
4768   assert(image != (Image *) NULL);
4769   assert(image->signature == MagickCoreSignature);
4770   for (i=0; i < (MagickPathExtent-1L); i++)
4771   {
4772     c=ReadBlobByte(image);
4773     if (c == EOF)
4774       {
4775         if (i == 0)
4776           return((char *) NULL);
4777         break;
4778       }
4779     string[i]=c;
4780     if (c == '\n')
4781       {
4782         if ((i > 0) && (string[i-1] == '\r'))
4783           i--;
4784         break;
4785       }
4786   }
4787   string[i]='\0';
4788   return(string);
4789 }
4790 
4791 /*
4792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4793 %                                                                             %
4794 %                                                                             %
4795 %                                                                             %
4796 +   R e f e r e n c e B l o b                                                 %
4797 %                                                                             %
4798 %                                                                             %
4799 %                                                                             %
4800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4801 %
4802 %  ReferenceBlob() increments the reference count associated with the pixel
4803 %  blob returning a pointer to the blob.
4804 %
4805 %  The format of the ReferenceBlob method is:
4806 %
4807 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
4808 %
4809 %  A description of each parameter follows:
4810 %
4811 %    o blob_info: the blob_info.
4812 %
4813 */
ReferenceBlob(BlobInfo * blob)4814 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4815 {
4816   assert(blob != (BlobInfo *) NULL);
4817   assert(blob->signature == MagickCoreSignature);
4818   if (blob->debug != MagickFalse)
4819     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4820   LockSemaphoreInfo(blob->semaphore);
4821   blob->reference_count++;
4822   UnlockSemaphoreInfo(blob->semaphore);
4823   return(blob);
4824 }
4825 
4826 /*
4827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4828 %                                                                             %
4829 %                                                                             %
4830 %                                                                             %
4831 +  S e e k B l o b                                                            %
4832 %                                                                             %
4833 %                                                                             %
4834 %                                                                             %
4835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4836 %
4837 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
4838 %  and returns the resulting offset.
4839 %
4840 %  The format of the SeekBlob method is:
4841 %
4842 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4843 %        const int whence)
4844 %
4845 %  A description of each parameter follows:
4846 %
4847 %    o image: the image.
4848 %
4849 %    o offset:  Specifies an integer representing the offset in bytes.
4850 %
4851 %    o whence:  Specifies an integer representing how the offset is
4852 %      treated relative to the beginning of the blob as follows:
4853 %
4854 %        SEEK_SET  Set position equal to offset bytes.
4855 %        SEEK_CUR  Set position to current location plus offset.
4856 %        SEEK_END  Set position to EOF plus offset.
4857 %
4858 */
SeekBlob(Image * image,const MagickOffsetType offset,const int whence)4859 MagickExport MagickOffsetType SeekBlob(Image *image,
4860   const MagickOffsetType offset,const int whence)
4861 {
4862   BlobInfo
4863     *magick_restrict blob_info;
4864 
4865   assert(image != (Image *) NULL);
4866   assert(image->signature == MagickCoreSignature);
4867   if (image->debug != MagickFalse)
4868     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4869   assert(image->blob != (BlobInfo *) NULL);
4870   assert(image->blob->type != UndefinedStream);
4871   blob_info=image->blob;
4872   switch (blob_info->type)
4873   {
4874     case UndefinedStream:
4875       break;
4876     case StandardStream:
4877     case PipeStream:
4878       return(-1);
4879     case FileStream:
4880     {
4881       if ((offset < 0) && (whence == SEEK_SET))
4882         return(-1);
4883       if (fseek(blob_info->file_info.file,offset,whence) < 0)
4884         return(-1);
4885       blob_info->offset=TellBlob(image);
4886       break;
4887     }
4888     case ZipStream:
4889     {
4890 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4891       if (gzseek(blob_info->file_info.gzfile,offset,whence) < 0)
4892         return(-1);
4893 #endif
4894       blob_info->offset=TellBlob(image);
4895       break;
4896     }
4897     case BZipStream:
4898       return(-1);
4899     case FifoStream:
4900       return(-1);
4901     case BlobStream:
4902     {
4903       switch (whence)
4904       {
4905         case SEEK_SET:
4906         default:
4907         {
4908           if (offset < 0)
4909             return(-1);
4910           blob_info->offset=offset;
4911           break;
4912         }
4913         case SEEK_CUR:
4914         {
4915           if (((offset > 0) && (blob_info->offset > (SSIZE_MAX-offset))) ||
4916               ((offset < 0) && (blob_info->offset < (-SSIZE_MAX-offset))))
4917             {
4918               errno=EOVERFLOW;
4919               return(-1);
4920             }
4921           if ((blob_info->offset+offset) < 0)
4922             return(-1);
4923           blob_info->offset+=offset;
4924           break;
4925         }
4926         case SEEK_END:
4927         {
4928           if (((MagickOffsetType) blob_info->length+offset) < 0)
4929             return(-1);
4930           blob_info->offset=blob_info->length+offset;
4931           break;
4932         }
4933       }
4934       if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
4935         {
4936           blob_info->eof=MagickFalse;
4937           break;
4938         }
4939       if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
4940         return(-1);
4941       break;
4942     }
4943     case CustomStream:
4944     {
4945       if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
4946         return(-1);
4947       blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
4948         blob_info->custom_stream->data);
4949       break;
4950     }
4951   }
4952   return(blob_info->offset);
4953 }
4954 
4955 /*
4956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4957 %                                                                             %
4958 %                                                                             %
4959 %                                                                             %
4960 +   S e t B l o b E x e m p t                                                 %
4961 %                                                                             %
4962 %                                                                             %
4963 %                                                                             %
4964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4965 %
4966 %  SetBlobExempt() sets the blob exempt status.
4967 %
4968 %  The format of the SetBlobExempt method is:
4969 %
4970 %      MagickBooleanType SetBlobExempt(const Image *image,
4971 %        const MagickBooleanType exempt)
4972 %
4973 %  A description of each parameter follows:
4974 %
4975 %    o image: the image.
4976 %
4977 %    o exempt: Set to true if this blob is exempt from being closed.
4978 %
4979 */
SetBlobExempt(Image * image,const MagickBooleanType exempt)4980 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4981 {
4982   assert(image != (const Image *) NULL);
4983   assert(image->signature == MagickCoreSignature);
4984   if (image->debug != MagickFalse)
4985     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4986   image->blob->exempt=exempt;
4987 }
4988 
4989 /*
4990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4991 %                                                                             %
4992 %                                                                             %
4993 %                                                                             %
4994 +  S e t B l o b E x t e n t                                                  %
4995 %                                                                             %
4996 %                                                                             %
4997 %                                                                             %
4998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4999 %
5000 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
5001 %  method is successful, subsequent writes to bytes in the specified range are
5002 %  guaranteed not to fail.
5003 %
5004 %  The format of the SetBlobExtent method is:
5005 %
5006 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
5007 %
5008 %  A description of each parameter follows:
5009 %
5010 %    o image: the image.
5011 %
5012 %    o extent:  the blob maximum extent.
5013 %
5014 */
SetBlobExtent(Image * image,const MagickSizeType extent)5015 MagickExport MagickBooleanType SetBlobExtent(Image *image,
5016   const MagickSizeType extent)
5017 {
5018   BlobInfo
5019     *magick_restrict blob_info;
5020 
5021   assert(image != (Image *) NULL);
5022   assert(image->signature == MagickCoreSignature);
5023   if (image->debug != MagickFalse)
5024     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5025   assert(image->blob != (BlobInfo *) NULL);
5026   assert(image->blob->type != UndefinedStream);
5027   blob_info=image->blob;
5028   switch (blob_info->type)
5029   {
5030     case UndefinedStream:
5031       break;
5032     case StandardStream:
5033       return(MagickFalse);
5034     case FileStream:
5035     {
5036       MagickOffsetType
5037         offset;
5038 
5039       ssize_t
5040         count;
5041 
5042       if (extent != (MagickSizeType) ((off_t) extent))
5043         return(MagickFalse);
5044       offset=SeekBlob(image,0,SEEK_END);
5045       if (offset < 0)
5046         return(MagickFalse);
5047       if ((MagickSizeType) offset >= extent)
5048         break;
5049       offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5050       if (offset < 0)
5051         break;
5052       count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5053         blob_info->file_info.file);
5054 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5055       if (blob_info->synchronize != MagickFalse)
5056         {
5057           int
5058             file;
5059 
5060           file=fileno(blob_info->file_info.file);
5061           if ((file == -1) || (offset < 0))
5062             return(MagickFalse);
5063           (void) posix_fallocate(file,offset,extent-offset);
5064         }
5065 #endif
5066       offset=SeekBlob(image,offset,SEEK_SET);
5067       if (count != 1)
5068         return(MagickFalse);
5069       break;
5070     }
5071     case PipeStream:
5072     case ZipStream:
5073       return(MagickFalse);
5074     case BZipStream:
5075       return(MagickFalse);
5076     case FifoStream:
5077       return(MagickFalse);
5078     case BlobStream:
5079     {
5080       if (extent != (MagickSizeType) ((size_t) extent))
5081         return(MagickFalse);
5082       if (blob_info->mapped != MagickFalse)
5083         {
5084           MagickOffsetType
5085             offset;
5086 
5087           ssize_t
5088             count;
5089 
5090           (void) UnmapBlob(blob_info->data,blob_info->length);
5091           RelinquishMagickResource(MapResource,blob_info->length);
5092           if (extent != (MagickSizeType) ((off_t) extent))
5093             return(MagickFalse);
5094           offset=SeekBlob(image,0,SEEK_END);
5095           if (offset < 0)
5096             return(MagickFalse);
5097           if ((MagickSizeType) offset >= extent)
5098             break;
5099           offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5100           count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5101             blob_info->file_info.file);
5102 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5103           if (blob_info->synchronize != MagickFalse)
5104             {
5105               int
5106                 file;
5107 
5108               file=fileno(blob_info->file_info.file);
5109               if ((file == -1) || (offset < 0))
5110                 return(MagickFalse);
5111               (void) posix_fallocate(file,offset,extent-offset);
5112             }
5113 #endif
5114           offset=SeekBlob(image,offset,SEEK_SET);
5115           if (count != 1)
5116             return(MagickFalse);
5117           (void) AcquireMagickResource(MapResource,extent);
5118           blob_info->data=(unsigned char*) MapBlob(fileno(
5119             blob_info->file_info.file),WriteMode,0,(size_t) extent);
5120           blob_info->extent=(size_t) extent;
5121           blob_info->length=(size_t) extent;
5122           (void) SyncBlob(image);
5123           break;
5124         }
5125       blob_info->extent=(size_t) extent;
5126       blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
5127         blob_info->extent+1,sizeof(*blob_info->data));
5128       (void) SyncBlob(image);
5129       if (blob_info->data == (unsigned char *) NULL)
5130         {
5131           (void) DetachBlob(blob_info);
5132           return(MagickFalse);
5133         }
5134       break;
5135     }
5136     case CustomStream:
5137       break;
5138   }
5139   return(MagickTrue);
5140 }
5141 
5142 /*
5143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5144 %                                                                             %
5145 %                                                                             %
5146 %                                                                             %
5147 +  S e t C u s t o m S t r e a m D a t a                                      %
5148 %                                                                             %
5149 %                                                                             %
5150 %                                                                             %
5151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5152 %
5153 %  SetCustomStreamData() sets the stream info data member.
5154 %
5155 %  The format of the SetCustomStreamData method is:
5156 %
5157 %      void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
5158 %
5159 %  A description of each parameter follows:
5160 %
5161 %    o custom_stream: the custom stream info.
5162 %
5163 %    o data: an object containing information about the custom stream.
5164 %
5165 */
SetCustomStreamData(CustomStreamInfo * custom_stream,void * data)5166 MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
5167   void *data)
5168 {
5169   assert(custom_stream != (CustomStreamInfo *) NULL);
5170   assert(custom_stream->signature == MagickCoreSignature);
5171   custom_stream->data=data;
5172 }
5173 
5174 /*
5175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5176 %                                                                             %
5177 %                                                                             %
5178 %                                                                             %
5179 +  S e t C u s t o m S t r e a m R e a d e r                                  %
5180 %                                                                             %
5181 %                                                                             %
5182 %                                                                             %
5183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5184 %
5185 %  SetCustomStreamReader() sets the stream info reader member.
5186 %
5187 %  The format of the SetCustomStreamReader method is:
5188 %
5189 %      void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5190 %        CustomStreamHandler reader)
5191 %
5192 %  A description of each parameter follows:
5193 %
5194 %    o custom_stream: the custom stream info.
5195 %
5196 %    o reader: a function to read from the stream.
5197 %
5198 */
SetCustomStreamReader(CustomStreamInfo * custom_stream,CustomStreamHandler reader)5199 MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5200   CustomStreamHandler reader)
5201 {
5202   assert(custom_stream != (CustomStreamInfo *) NULL);
5203   assert(custom_stream->signature == MagickCoreSignature);
5204   custom_stream->reader=reader;
5205 }
5206 
5207 /*
5208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5209 %                                                                             %
5210 %                                                                             %
5211 %                                                                             %
5212 +  S e t C u s t o m S t r e a m S e e k e r                                  %
5213 %                                                                             %
5214 %                                                                             %
5215 %                                                                             %
5216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5217 %
5218 %  SetCustomStreamSeeker() sets the stream info seeker member.
5219 %
5220 %  The format of the SetCustomStreamReader method is:
5221 %
5222 %      void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5223 %        CustomStreamSeeker seeker)
5224 %
5225 %  A description of each parameter follows:
5226 %
5227 %    o custom_stream: the custom stream info.
5228 %
5229 %    o seeker: a function to seek in the custom stream.
5230 %
5231 */
SetCustomStreamSeeker(CustomStreamInfo * custom_stream,CustomStreamSeeker seeker)5232 MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5233   CustomStreamSeeker seeker)
5234 {
5235   assert(custom_stream != (CustomStreamInfo *) NULL);
5236   assert(custom_stream->signature == MagickCoreSignature);
5237   custom_stream->seeker=seeker;
5238 }
5239 
5240 /*
5241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5242 %                                                                             %
5243 %                                                                             %
5244 %                                                                             %
5245 +  S e t C u s t o m S t r e a m T e l l e r                                  %
5246 %                                                                             %
5247 %                                                                             %
5248 %                                                                             %
5249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5250 %
5251 %  SetCustomStreamTeller() sets the stream info teller member.
5252 %
5253 %  The format of the SetCustomStreamTeller method is:
5254 %
5255 %      void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5256 %        CustomStreamTeller *teller)
5257 %
5258 %  A description of each parameter follows:
5259 %
5260 %    o custom_stream: the custom stream info.
5261 %
5262 %    o teller: a function to set the position in the stream.
5263 %
5264 */
SetCustomStreamTeller(CustomStreamInfo * custom_stream,CustomStreamTeller teller)5265 MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5266   CustomStreamTeller teller)
5267 {
5268   assert(custom_stream != (CustomStreamInfo *) NULL);
5269   assert(custom_stream->signature == MagickCoreSignature);
5270   custom_stream->teller=teller;
5271 }
5272 
5273 /*
5274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5275 %                                                                             %
5276 %                                                                             %
5277 %                                                                             %
5278 +  S e t C u s t o m S t r e a m W r i t e r                                  %
5279 %                                                                             %
5280 %                                                                             %
5281 %                                                                             %
5282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5283 %
5284 %  SetCustomStreamWriter() sets the stream info writer member.
5285 %
5286 %  The format of the SetCustomStreamWriter method is:
5287 %
5288 %      void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5289 %        CustomStreamHandler *writer)
5290 %
5291 %  A description of each parameter follows:
5292 %
5293 %    o custom_stream: the custom stream info.
5294 %
5295 %    o writer: a function to write to the custom stream.
5296 %
5297 */
SetCustomStreamWriter(CustomStreamInfo * custom_stream,CustomStreamHandler writer)5298 MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5299   CustomStreamHandler writer)
5300 {
5301   assert(custom_stream != (CustomStreamInfo *) NULL);
5302   assert(custom_stream->signature == MagickCoreSignature);
5303   custom_stream->writer=writer;
5304 }
5305 
5306 /*
5307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5308 %                                                                             %
5309 %                                                                             %
5310 %                                                                             %
5311 +  S y n c B l o b                                                            %
5312 %                                                                             %
5313 %                                                                             %
5314 %                                                                             %
5315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5316 %
5317 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
5318 %  attributes if it is an blob.
5319 %
5320 %  The format of the SyncBlob method is:
5321 %
5322 %      int SyncBlob(Image *image)
5323 %
5324 %  A description of each parameter follows:
5325 %
5326 %    o image: the image.
5327 %
5328 */
SyncBlob(Image * image)5329 static int SyncBlob(Image *image)
5330 {
5331   BlobInfo
5332     *magick_restrict blob_info;
5333 
5334   int
5335     status;
5336 
5337   assert(image != (Image *) NULL);
5338   assert(image->signature == MagickCoreSignature);
5339   if (image->debug != MagickFalse)
5340     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5341   assert(image->blob != (BlobInfo *) NULL);
5342   assert(image->blob->type != UndefinedStream);
5343   blob_info=image->blob;
5344   status=0;
5345   switch (blob_info->type)
5346   {
5347     case UndefinedStream:
5348     case StandardStream:
5349       break;
5350     case FileStream:
5351     case PipeStream:
5352     {
5353       status=fflush(blob_info->file_info.file);
5354       break;
5355     }
5356     case ZipStream:
5357     {
5358 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5359       status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5360 #endif
5361       break;
5362     }
5363     case BZipStream:
5364     {
5365 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5366       status=BZ2_bzflush(blob_info->file_info.bzfile);
5367 #endif
5368       break;
5369     }
5370     case FifoStream:
5371       break;
5372     case BlobStream:
5373       break;
5374     case CustomStream:
5375       break;
5376   }
5377   return(status);
5378 }
5379 
5380 /*
5381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5382 %                                                                             %
5383 %                                                                             %
5384 %                                                                             %
5385 +  T e l l B l o b                                                            %
5386 %                                                                             %
5387 %                                                                             %
5388 %                                                                             %
5389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5390 %
5391 %  TellBlob() obtains the current value of the blob or file position.
5392 %
5393 %  The format of the TellBlob method is:
5394 %
5395 %      MagickOffsetType TellBlob(const Image *image)
5396 %
5397 %  A description of each parameter follows:
5398 %
5399 %    o image: the image.
5400 %
5401 */
TellBlob(const Image * image)5402 MagickExport MagickOffsetType TellBlob(const Image *image)
5403 {
5404   BlobInfo
5405     *magick_restrict blob_info;
5406 
5407   MagickOffsetType
5408     offset;
5409 
5410   assert(image != (Image *) NULL);
5411   assert(image->signature == MagickCoreSignature);
5412   if (image->debug != MagickFalse)
5413     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5414   assert(image->blob != (BlobInfo *) NULL);
5415   assert(image->blob->type != UndefinedStream);
5416   blob_info=image->blob;
5417   offset=(-1);
5418   switch (blob_info->type)
5419   {
5420     case UndefinedStream:
5421     case StandardStream:
5422       break;
5423     case FileStream:
5424     {
5425       offset=ftell(blob_info->file_info.file);
5426       break;
5427     }
5428     case PipeStream:
5429       break;
5430     case ZipStream:
5431     {
5432 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5433       offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5434 #endif
5435       break;
5436     }
5437     case BZipStream:
5438       break;
5439     case FifoStream:
5440       break;
5441     case BlobStream:
5442     {
5443       offset=blob_info->offset;
5444       break;
5445     }
5446     case CustomStream:
5447     {
5448       if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5449         offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5450       break;
5451     }
5452   }
5453   return(offset);
5454 }
5455 
5456 /*
5457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5458 %                                                                             %
5459 %                                                                             %
5460 %                                                                             %
5461 +  U n m a p B l o b                                                          %
5462 %                                                                             %
5463 %                                                                             %
5464 %                                                                             %
5465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5466 %
5467 %  UnmapBlob() deallocates the binary large object previously allocated with
5468 %  the MapBlob method.
5469 %
5470 %  The format of the UnmapBlob method is:
5471 %
5472 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
5473 %
5474 %  A description of each parameter follows:
5475 %
5476 %    o map: the address  of the binary large object.
5477 %
5478 %    o length: the length of the binary large object.
5479 %
5480 */
UnmapBlob(void * map,const size_t length)5481 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5482 {
5483 #if defined(MAGICKCORE_HAVE_MMAP)
5484   int
5485     status;
5486 
5487   status=munmap(map,length);
5488   return(status == -1 ? MagickFalse : MagickTrue);
5489 #else
5490   (void) map;
5491   (void) length;
5492   return(MagickFalse);
5493 #endif
5494 }
5495 
5496 /*
5497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5498 %                                                                             %
5499 %                                                                             %
5500 %                                                                             %
5501 +  W r i t e B l o b                                                          %
5502 %                                                                             %
5503 %                                                                             %
5504 %                                                                             %
5505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5506 %
5507 %  WriteBlob() writes data to a blob or image file.  It returns the number of
5508 %  bytes written.
5509 %
5510 %  The format of the WriteBlob method is:
5511 %
5512 %      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5513 %
5514 %  A description of each parameter follows:
5515 %
5516 %    o image: the image.
5517 %
5518 %    o length:  Specifies an integer representing the number of bytes to
5519 %      write to the file.
5520 %
5521 %    o data:  The address of the data to write to the blob or file.
5522 %
5523 */
WriteBlob(Image * image,const size_t length,const void * data)5524 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5525   const void *data)
5526 {
5527   BlobInfo
5528     *magick_restrict blob_info;
5529 
5530   int
5531     c;
5532 
5533   register const unsigned char
5534     *p;
5535 
5536   register unsigned char
5537     *q;
5538 
5539   ssize_t
5540     count;
5541 
5542   assert(image != (Image *) NULL);
5543   assert(image->signature == MagickCoreSignature);
5544   assert(image->blob != (BlobInfo *) NULL);
5545   assert(image->blob->type != UndefinedStream);
5546   if (length == 0)
5547     return(0);
5548   assert(data != (const void *) NULL);
5549   blob_info=image->blob;
5550   count=0;
5551   p=(const unsigned char *) data;
5552   q=(unsigned char *) data;
5553   switch (blob_info->type)
5554   {
5555     case UndefinedStream:
5556       break;
5557     case StandardStream:
5558     case FileStream:
5559     case PipeStream:
5560     {
5561       switch (length)
5562       {
5563         default:
5564         {
5565           count=(ssize_t) fwrite((const char *) data,1,length,
5566             blob_info->file_info.file);
5567           break;
5568         }
5569         case 4:
5570         {
5571           c=putc((int) *p++,blob_info->file_info.file);
5572           if (c == EOF)
5573             break;
5574           count++;
5575         }
5576         case 3:
5577         {
5578           c=putc((int) *p++,blob_info->file_info.file);
5579           if (c == EOF)
5580             break;
5581           count++;
5582         }
5583         case 2:
5584         {
5585           c=putc((int) *p++,blob_info->file_info.file);
5586           if (c == EOF)
5587             break;
5588           count++;
5589         }
5590         case 1:
5591         {
5592           c=putc((int) *p++,blob_info->file_info.file);
5593           if (c == EOF)
5594             break;
5595           count++;
5596         }
5597         case 0:
5598           break;
5599       }
5600       break;
5601     }
5602     case ZipStream:
5603     {
5604 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5605       switch (length)
5606       {
5607         default:
5608         {
5609           register ssize_t
5610             i;
5611 
5612           for (i=0; i < (ssize_t) length; i+=count)
5613           {
5614             count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
5615               (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
5616             if (count <= 0)
5617               {
5618                 count=0;
5619                 if (errno != EINTR)
5620                   break;
5621               }
5622           }
5623           count=i;
5624           break;
5625         }
5626         case 4:
5627         {
5628           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5629           if (c == EOF)
5630             break;
5631           count++;
5632         }
5633         case 3:
5634         {
5635           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5636           if (c == EOF)
5637             break;
5638           count++;
5639         }
5640         case 2:
5641         {
5642           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5643           if (c == EOF)
5644             break;
5645           count++;
5646         }
5647         case 1:
5648         {
5649           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5650           if (c == EOF)
5651             break;
5652           count++;
5653         }
5654         case 0:
5655           break;
5656       }
5657 #endif
5658       break;
5659     }
5660     case BZipStream:
5661     {
5662 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5663       register ssize_t
5664         i;
5665 
5666       for (i=0; i < (ssize_t) length; i+=count)
5667       {
5668         count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5669           (int) MagickMin(length-i,MagickMaxBufferExtent));
5670         if (count <= 0)
5671           {
5672             count=0;
5673             if (errno != EINTR)
5674               break;
5675           }
5676       }
5677       count=i;
5678 #endif
5679       break;
5680     }
5681     case FifoStream:
5682     {
5683       count=(ssize_t) blob_info->stream(image,data,length);
5684       break;
5685     }
5686     case BlobStream:
5687     {
5688       if ((blob_info->offset+(MagickOffsetType) length) >=
5689           (MagickOffsetType) blob_info->extent)
5690         {
5691           if (blob_info->mapped != MagickFalse)
5692             return(0);
5693           blob_info->extent+=length+blob_info->quantum;
5694           blob_info->quantum<<=1;
5695           blob_info->data=(unsigned char *) ResizeQuantumMemory(
5696             blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5697           (void) SyncBlob(image);
5698           if (blob_info->data == (unsigned char *) NULL)
5699             {
5700               (void) DetachBlob(blob_info);
5701               return(0);
5702             }
5703         }
5704       q=blob_info->data+blob_info->offset;
5705       (void) memcpy(q,p,length);
5706       blob_info->offset+=length;
5707       if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5708         blob_info->length=(size_t) blob_info->offset;
5709       count=(ssize_t) length;
5710       break;
5711     }
5712     case CustomStream:
5713     {
5714       if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
5715         count=blob_info->custom_stream->writer((unsigned char *) data,
5716           length,blob_info->custom_stream->data);
5717       break;
5718     }
5719   }
5720   return(count);
5721 }
5722 
5723 /*
5724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5725 %                                                                             %
5726 %                                                                             %
5727 %                                                                             %
5728 +  W r i t e B l o b B y t e                                                  %
5729 %                                                                             %
5730 %                                                                             %
5731 %                                                                             %
5732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5733 %
5734 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
5735 %  written (either 0 or 1);
5736 %
5737 %  The format of the WriteBlobByte method is:
5738 %
5739 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
5740 %
5741 %  A description of each parameter follows.
5742 %
5743 %    o image: the image.
5744 %
5745 %    o value: Specifies the value to write.
5746 %
5747 */
WriteBlobByte(Image * image,const unsigned char value)5748 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5749 {
5750   BlobInfo
5751     *magick_restrict blob_info;
5752 
5753   ssize_t
5754     count;
5755 
5756   assert(image != (Image *) NULL);
5757   assert(image->signature == MagickCoreSignature);
5758   assert(image->blob != (BlobInfo *) NULL);
5759   assert(image->blob->type != UndefinedStream);
5760   blob_info=image->blob;
5761   count=0;
5762   switch (blob_info->type)
5763   {
5764     case StandardStream:
5765     case FileStream:
5766     case PipeStream:
5767     {
5768       int
5769         c;
5770 
5771       c=putc((int) value,blob_info->file_info.file);
5772       if (c == EOF)
5773         break;
5774       count++;
5775       break;
5776     }
5777     default:
5778     {
5779       count=WriteBlobStream(image,1,&value);
5780       break;
5781     }
5782   }
5783   return(count);
5784 }
5785 
5786 /*
5787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5788 %                                                                             %
5789 %                                                                             %
5790 %                                                                             %
5791 +  W r i t e B l o b F l o a t                                                %
5792 %                                                                             %
5793 %                                                                             %
5794 %                                                                             %
5795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5796 %
5797 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5798 %  specified by the endian member of the image structure.
5799 %
5800 %  The format of the WriteBlobFloat method is:
5801 %
5802 %      ssize_t WriteBlobFloat(Image *image,const float value)
5803 %
5804 %  A description of each parameter follows.
5805 %
5806 %    o image: the image.
5807 %
5808 %    o value: Specifies the value to write.
5809 %
5810 */
WriteBlobFloat(Image * image,const float value)5811 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5812 {
5813   union
5814   {
5815     unsigned int
5816       unsigned_value;
5817 
5818     float
5819       float_value;
5820   } quantum;
5821 
5822   quantum.unsigned_value=0U;
5823   quantum.float_value=value;
5824   return(WriteBlobLong(image,quantum.unsigned_value));
5825 }
5826 
5827 /*
5828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5829 %                                                                             %
5830 %                                                                             %
5831 %                                                                             %
5832 +  W r i t e B l o b L o n g                                                  %
5833 %                                                                             %
5834 %                                                                             %
5835 %                                                                             %
5836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5837 %
5838 %  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5839 %  byte-order specified by the endian member of the image structure.
5840 %
5841 %  The format of the WriteBlobLong method is:
5842 %
5843 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
5844 %
5845 %  A description of each parameter follows.
5846 %
5847 %    o image: the image.
5848 %
5849 %    o value: Specifies the value to write.
5850 %
5851 */
WriteBlobLong(Image * image,const unsigned int value)5852 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5853 {
5854   unsigned char
5855     buffer[4];
5856 
5857   assert(image != (Image *) NULL);
5858   assert(image->signature == MagickCoreSignature);
5859   if (image->endian == LSBEndian)
5860     {
5861       buffer[0]=(unsigned char) value;
5862       buffer[1]=(unsigned char) (value >> 8);
5863       buffer[2]=(unsigned char) (value >> 16);
5864       buffer[3]=(unsigned char) (value >> 24);
5865       return(WriteBlobStream(image,4,buffer));
5866     }
5867   buffer[0]=(unsigned char) (value >> 24);
5868   buffer[1]=(unsigned char) (value >> 16);
5869   buffer[2]=(unsigned char) (value >> 8);
5870   buffer[3]=(unsigned char) value;
5871   return(WriteBlobStream(image,4,buffer));
5872 }
5873 
5874 /*
5875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5876 %                                                                             %
5877 %                                                                             %
5878 %                                                                             %
5879 +  W r i t e B l o b L o n g L o n g                                          %
5880 %                                                                             %
5881 %                                                                             %
5882 %                                                                             %
5883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5884 %
5885 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
5886 %  byte-order specified by the endian member of the image structure.
5887 %
5888 %  The format of the WriteBlobLongLong method is:
5889 %
5890 %      ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5891 %
5892 %  A description of each parameter follows.
5893 %
5894 %    o value:  Specifies the value to write.
5895 %
5896 %    o image: the image.
5897 %
5898 */
WriteBlobLongLong(Image * image,const MagickSizeType value)5899 MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5900 {
5901   unsigned char
5902     buffer[8];
5903 
5904   assert(image != (Image *) NULL);
5905   assert(image->signature == MagickCoreSignature);
5906   if (image->endian == LSBEndian)
5907     {
5908       buffer[0]=(unsigned char) value;
5909       buffer[1]=(unsigned char) (value >> 8);
5910       buffer[2]=(unsigned char) (value >> 16);
5911       buffer[3]=(unsigned char) (value >> 24);
5912       buffer[4]=(unsigned char) (value >> 32);
5913       buffer[5]=(unsigned char) (value >> 40);
5914       buffer[6]=(unsigned char) (value >> 48);
5915       buffer[7]=(unsigned char) (value >> 56);
5916       return(WriteBlobStream(image,8,buffer));
5917     }
5918   buffer[0]=(unsigned char) (value >> 56);
5919   buffer[1]=(unsigned char) (value >> 48);
5920   buffer[2]=(unsigned char) (value >> 40);
5921   buffer[3]=(unsigned char) (value >> 32);
5922   buffer[4]=(unsigned char) (value >> 24);
5923   buffer[5]=(unsigned char) (value >> 16);
5924   buffer[6]=(unsigned char) (value >> 8);
5925   buffer[7]=(unsigned char) value;
5926   return(WriteBlobStream(image,8,buffer));
5927 }
5928 
5929 /*
5930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5931 %                                                                             %
5932 %                                                                             %
5933 %                                                                             %
5934 +   W r i t e B l o b S h o r t                                               %
5935 %                                                                             %
5936 %                                                                             %
5937 %                                                                             %
5938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5939 %
5940 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
5941 %  byte-order specified by the endian member of the image structure.
5942 %
5943 %  The format of the WriteBlobShort method is:
5944 %
5945 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
5946 %
5947 %  A description of each parameter follows.
5948 %
5949 %    o image: the image.
5950 %
5951 %    o value:  Specifies the value to write.
5952 %
5953 */
WriteBlobShort(Image * image,const unsigned short value)5954 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5955 {
5956   unsigned char
5957     buffer[2];
5958 
5959   assert(image != (Image *) NULL);
5960   assert(image->signature == MagickCoreSignature);
5961   if (image->endian == LSBEndian)
5962     {
5963       buffer[0]=(unsigned char) value;
5964       buffer[1]=(unsigned char) (value >> 8);
5965       return(WriteBlobStream(image,2,buffer));
5966     }
5967   buffer[0]=(unsigned char) (value >> 8);
5968   buffer[1]=(unsigned char) value;
5969   return(WriteBlobStream(image,2,buffer));
5970 }
5971 
5972 /*
5973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5974 %                                                                             %
5975 %                                                                             %
5976 %                                                                             %
5977 +  W r i t e B l o b S i g n e d L o n g                                      %
5978 %                                                                             %
5979 %                                                                             %
5980 %                                                                             %
5981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5982 %
5983 %  WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
5984 %  byte-order specified by the endian member of the image structure.
5985 %
5986 %  The format of the WriteBlobSignedLong method is:
5987 %
5988 %      ssize_t WriteBlobSignedLong(Image *image,const signed int value)
5989 %
5990 %  A description of each parameter follows.
5991 %
5992 %    o image: the image.
5993 %
5994 %    o value: Specifies the value to write.
5995 %
5996 */
WriteBlobSignedLong(Image * image,const signed int value)5997 MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
5998 {
5999   union
6000   {
6001     unsigned int
6002       unsigned_value;
6003 
6004     signed int
6005       signed_value;
6006   } quantum;
6007 
6008   unsigned char
6009     buffer[4];
6010 
6011   assert(image != (Image *) NULL);
6012   assert(image->signature == MagickCoreSignature);
6013   quantum.signed_value=value;
6014   if (image->endian == LSBEndian)
6015     {
6016       buffer[0]=(unsigned char) quantum.unsigned_value;
6017       buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6018       buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6019       buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6020       return(WriteBlobStream(image,4,buffer));
6021     }
6022   buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
6023   buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
6024   buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
6025   buffer[3]=(unsigned char) quantum.unsigned_value;
6026   return(WriteBlobStream(image,4,buffer));
6027 }
6028 
6029 /*
6030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6031 %                                                                             %
6032 %                                                                             %
6033 %                                                                             %
6034 +  W r i t e B l o b L S B L o n g                                            %
6035 %                                                                             %
6036 %                                                                             %
6037 %                                                                             %
6038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6039 %
6040 %  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
6041 %  least-significant byte first order.
6042 %
6043 %  The format of the WriteBlobLSBLong method is:
6044 %
6045 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6046 %
6047 %  A description of each parameter follows.
6048 %
6049 %    o image: the image.
6050 %
6051 %    o value: Specifies the value to write.
6052 %
6053 */
WriteBlobLSBLong(Image * image,const unsigned int value)6054 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6055 {
6056   unsigned char
6057     buffer[4];
6058 
6059   assert(image != (Image *) NULL);
6060   assert(image->signature == MagickCoreSignature);
6061   buffer[0]=(unsigned char) value;
6062   buffer[1]=(unsigned char) (value >> 8);
6063   buffer[2]=(unsigned char) (value >> 16);
6064   buffer[3]=(unsigned char) (value >> 24);
6065   return(WriteBlobStream(image,4,buffer));
6066 }
6067 
6068 /*
6069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6070 %                                                                             %
6071 %                                                                             %
6072 %                                                                             %
6073 +   W r i t e B l o b L S B S h o r t                                         %
6074 %                                                                             %
6075 %                                                                             %
6076 %                                                                             %
6077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6078 %
6079 %  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
6080 %  least-significant byte first order.
6081 %
6082 %  The format of the WriteBlobLSBShort method is:
6083 %
6084 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6085 %
6086 %  A description of each parameter follows.
6087 %
6088 %    o image: the image.
6089 %
6090 %    o value:  Specifies the value to write.
6091 %
6092 */
WriteBlobLSBShort(Image * image,const unsigned short value)6093 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6094 {
6095   unsigned char
6096     buffer[2];
6097 
6098   assert(image != (Image *) NULL);
6099   assert(image->signature == MagickCoreSignature);
6100   buffer[0]=(unsigned char) value;
6101   buffer[1]=(unsigned char) (value >> 8);
6102   return(WriteBlobStream(image,2,buffer));
6103 }
6104 
6105 /*
6106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6107 %                                                                             %
6108 %                                                                             %
6109 %                                                                             %
6110 +  W r i t e B l o b L S B S i g n e d L o n g                                %
6111 %                                                                             %
6112 %                                                                             %
6113 %                                                                             %
6114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6115 %
6116 %  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
6117 %  least-significant byte first order.
6118 %
6119 %  The format of the WriteBlobLSBSignedLong method is:
6120 %
6121 %      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6122 %
6123 %  A description of each parameter follows.
6124 %
6125 %    o image: the image.
6126 %
6127 %    o value: Specifies the value to write.
6128 %
6129 */
WriteBlobLSBSignedLong(Image * image,const signed int value)6130 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6131 {
6132   union
6133   {
6134     unsigned int
6135       unsigned_value;
6136 
6137     signed int
6138       signed_value;
6139   } quantum;
6140 
6141   unsigned char
6142     buffer[4];
6143 
6144   assert(image != (Image *) NULL);
6145   assert(image->signature == MagickCoreSignature);
6146   quantum.signed_value=value;
6147   buffer[0]=(unsigned char) quantum.unsigned_value;
6148   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6149   buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6150   buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6151   return(WriteBlobStream(image,4,buffer));
6152 }
6153 
6154 /*
6155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6156 %                                                                             %
6157 %                                                                             %
6158 %                                                                             %
6159 +   W r i t e B l o b L S B S i g n e d S h o r t                             %
6160 %                                                                             %
6161 %                                                                             %
6162 %                                                                             %
6163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6164 %
6165 %  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
6166 %  in least-significant byte first order.
6167 %
6168 %  The format of the WriteBlobLSBSignedShort method is:
6169 %
6170 %      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
6171 %
6172 %  A description of each parameter follows.
6173 %
6174 %    o image: the image.
6175 %
6176 %    o value:  Specifies the value to write.
6177 %
6178 */
WriteBlobLSBSignedShort(Image * image,const signed short value)6179 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
6180   const signed short value)
6181 {
6182   union
6183   {
6184     unsigned short
6185       unsigned_value;
6186 
6187     signed short
6188       signed_value;
6189   } quantum;
6190 
6191   unsigned char
6192     buffer[2];
6193 
6194   assert(image != (Image *) NULL);
6195   assert(image->signature == MagickCoreSignature);
6196   quantum.signed_value=value;
6197   buffer[0]=(unsigned char) quantum.unsigned_value;
6198   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6199   return(WriteBlobStream(image,2,buffer));
6200 }
6201 
6202 /*
6203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6204 %                                                                             %
6205 %                                                                             %
6206 %                                                                             %
6207 +  W r i t e B l o b M S B L o n g                                            %
6208 %                                                                             %
6209 %                                                                             %
6210 %                                                                             %
6211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6212 %
6213 %  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
6214 %  most-significant byte first order.
6215 %
6216 %  The format of the WriteBlobMSBLong method is:
6217 %
6218 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6219 %
6220 %  A description of each parameter follows.
6221 %
6222 %    o value:  Specifies the value to write.
6223 %
6224 %    o image: the image.
6225 %
6226 */
WriteBlobMSBLong(Image * image,const unsigned int value)6227 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6228 {
6229   unsigned char
6230     buffer[4];
6231 
6232   assert(image != (Image *) NULL);
6233   assert(image->signature == MagickCoreSignature);
6234   buffer[0]=(unsigned char) (value >> 24);
6235   buffer[1]=(unsigned char) (value >> 16);
6236   buffer[2]=(unsigned char) (value >> 8);
6237   buffer[3]=(unsigned char) value;
6238   return(WriteBlobStream(image,4,buffer));
6239 }
6240 
6241 /*
6242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6243 %                                                                             %
6244 %                                                                             %
6245 %                                                                             %
6246 +   W r i t e B l o b M S B S i g n e d S h o r t                             %
6247 %                                                                             %
6248 %                                                                             %
6249 %                                                                             %
6250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6251 %
6252 %  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
6253 %  in most-significant byte first order.
6254 %
6255 %  The format of the WriteBlobMSBSignedShort method is:
6256 %
6257 %      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
6258 %
6259 %  A description of each parameter follows.
6260 %
6261 %    o image: the image.
6262 %
6263 %    o value:  Specifies the value to write.
6264 %
6265 */
WriteBlobMSBSignedShort(Image * image,const signed short value)6266 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
6267   const signed short value)
6268 {
6269   union
6270   {
6271     unsigned short
6272       unsigned_value;
6273 
6274     signed short
6275       signed_value;
6276   } quantum;
6277 
6278   unsigned char
6279     buffer[2];
6280 
6281   assert(image != (Image *) NULL);
6282   assert(image->signature == MagickCoreSignature);
6283   quantum.signed_value=value;
6284   buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
6285   buffer[1]=(unsigned char) quantum.unsigned_value;
6286   return(WriteBlobStream(image,2,buffer));
6287 }
6288 
6289 /*
6290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6291 %                                                                             %
6292 %                                                                             %
6293 %                                                                             %
6294 +  W r i t e B l o b M S B S h o r t                                          %
6295 %                                                                             %
6296 %                                                                             %
6297 %                                                                             %
6298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6299 %
6300 %  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6301 %  most-significant byte first order.
6302 %
6303 %  The format of the WriteBlobMSBShort method is:
6304 %
6305 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6306 %
6307 %  A description of each parameter follows.
6308 %
6309 %   o  value:  Specifies the value to write.
6310 %
6311 %   o  file:  Specifies the file to write the data to.
6312 %
6313 */
WriteBlobMSBShort(Image * image,const unsigned short value)6314 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6315 {
6316   unsigned char
6317     buffer[2];
6318 
6319   assert(image != (Image *) NULL);
6320   assert(image->signature == MagickCoreSignature);
6321   buffer[0]=(unsigned char) (value >> 8);
6322   buffer[1]=(unsigned char) value;
6323   return(WriteBlobStream(image,2,buffer));
6324 }
6325 
6326 /*
6327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6328 %                                                                             %
6329 %                                                                             %
6330 %                                                                             %
6331 +  W r i t e B l o b S t r i n g                                              %
6332 %                                                                             %
6333 %                                                                             %
6334 %                                                                             %
6335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6336 %
6337 %  WriteBlobString() write a string to a blob.  It returns the number of
6338 %  characters written.
6339 %
6340 %  The format of the WriteBlobString method is:
6341 %
6342 %      ssize_t WriteBlobString(Image *image,const char *string)
6343 %
6344 %  A description of each parameter follows.
6345 %
6346 %    o image: the image.
6347 %
6348 %    o string: Specifies the string to write.
6349 %
6350 */
WriteBlobString(Image * image,const char * string)6351 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6352 {
6353   assert(image != (Image *) NULL);
6354   assert(image->signature == MagickCoreSignature);
6355   assert(string != (const char *) NULL);
6356   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
6357 }
6358