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