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