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