/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % BBBB L OOO BBBB % % B B L O O B B % % BBBB L O O BBBB % % B B L O O B B % % BBBB LLLLL OOO BBBB % % % % % % MagickCore Binary Large OBjectS Methods % % % % Software Design % % John Cristy % % July 1999 % % % % % % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % % dedicated to making software imaging solutions freely available. % % % % You may not use this file except in compliance with the License. You may % % obtain a copy of the License at % % % % http://www.imagemagick.org/script/license.php % % % % Unless required by applicable law or agreed to in writing, software % % distributed under the License is distributed on an "AS IS" BASIS, % % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % % See the License for the specific language governing permissions and % % limitations under the License. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % */ /* Include declarations. */ #include "MagickCore/studio.h" #include "MagickCore/nt-base-private.h" #include "MagickCore/blob.h" #include "MagickCore/blob-private.h" #include "MagickCore/cache.h" #include "MagickCore/client.h" #include "MagickCore/constitute.h" #include "MagickCore/delegate.h" #include "MagickCore/exception.h" #include "MagickCore/exception-private.h" #include "MagickCore/image-private.h" #include "MagickCore/list.h" #include "MagickCore/locale_.h" #include "MagickCore/log.h" #include "MagickCore/magick.h" #include "MagickCore/memory_.h" #include "MagickCore/policy.h" #include "MagickCore/resource_.h" #include "MagickCore/semaphore.h" #include "MagickCore/string_.h" #include "MagickCore/string-private.h" #include "MagickCore/token.h" #include "MagickCore/utility.h" #include "MagickCore/utility-private.h" #if defined(MAGICKCORE_HAVE_MMAP_FILEIO) && !defined(MAGICKCORE_WINDOWS_SUPPORT) # include #endif #if defined(MAGICKCORE_ZLIB_DELEGATE) #include "zlib.h" #endif #if defined(MAGICKCORE_BZLIB_DELEGATE) #include "bzlib.h" #endif /* Define declarations. */ #define MagickMaxBlobExtent 65541 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) # define MAP_ANONYMOUS MAP_ANON #endif #if !defined(MAP_FAILED) #define MAP_FAILED ((void *) -1) #endif #if !defined(MS_SYNC) #define MS_SYNC 0x04 #endif #if defined(__OS2__) #include #define _O_BINARY O_BINARY #endif /* Typedef declarations. */ typedef union FileInfo { FILE *file; #if defined(MAGICKCORE_ZLIB_DELEGATE) gzFile gzfile; #endif #if defined(MAGICKCORE_BZLIB_DELEGATE) BZFILE *bzfile; #endif } FileInfo; struct _BlobInfo { size_t length, extent, quantum; MagickBooleanType mapped, eof; MagickOffsetType offset; MagickSizeType size; MagickBooleanType exempt, synchronize, status, temporary; StreamType type; FileInfo file_info; struct stat properties; StreamHandler stream; unsigned char *data; MagickBooleanType debug; SemaphoreInfo *semaphore; ssize_t reference_count; size_t signature; }; /* Forward declarations. */ static int SyncBlob(Image *); /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + A t t a c h B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AttachBlob() attaches a blob to the BlobInfo structure. % % The format of the AttachBlob method is: % % void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length) % % A description of each parameter follows: % % o blob_info: Specifies a pointer to a BlobInfo structure. % % o blob: the address of a character stream in one of the image formats % understood by ImageMagick. % % o length: This size_t integer reflects the length in bytes of the blob. % */ MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob, const size_t length) { assert(blob_info != (BlobInfo *) NULL); if (blob_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); blob_info->length=length; blob_info->extent=length; blob_info->quantum=(size_t) MagickMaxBlobExtent; blob_info->offset=0; blob_info->type=BlobStream; blob_info->file_info.file=(FILE *) NULL; blob_info->data=(unsigned char *) blob; blob_info->mapped=MagickFalse; } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + B l o b T o F i l e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % BlobToFile() writes a blob to a file. It returns MagickFalse if an error % occurs otherwise MagickTrue. % % The format of the BlobToFile method is: % % MagickBooleanType BlobToFile(char *filename,const void *blob, % const size_t length,ExceptionInfo *exception) % % A description of each parameter follows: % % o filename: Write the blob to this file. % % o blob: the address of a blob. % % o length: This length in bytes of the blob. % % o exception: return any errors or warnings in this structure. % */ static inline MagickSizeType MagickMin(const MagickSizeType x, const MagickSizeType y) { if (x < y) return(x); return(y); } MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob, const size_t length,ExceptionInfo *exception) { int file; register size_t i; ssize_t count; assert(filename != (const char *) NULL); (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); assert(blob != (const void *) NULL); if (*filename == '\0') file=AcquireUniqueFileResource(filename); else file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE); if (file == -1) { ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); return(MagickFalse); } for (i=0; i < length; i+=count) { count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length- i,(MagickSizeType) SSIZE_MAX)); if (count <= 0) { count=0; if (errno != EINTR) break; } } file=close(file); if ((file == -1) || (i < length)) { ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); return(MagickFalse); } return(MagickTrue); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % B l o b T o I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % BlobToImage() implements direct to memory image formats. It returns the % blob as an image. % % The format of the BlobToImage method is: % % Image *BlobToImage(const ImageInfo *image_info,const void *blob, % const size_t length,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o blob: the address of a character stream in one of the image formats % understood by ImageMagick. % % o length: This size_t integer reflects the length in bytes of the blob. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob, const size_t length,ExceptionInfo *exception) { const MagickInfo *magick_info; Image *image; ImageInfo *blob_info, *clone_info; MagickBooleanType status; assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); if ((blob == (const void *) NULL) || (length == 0)) { (void) ThrowMagickException(exception,GetMagickModule(),BlobError, "ZeroLengthBlobNotPermitted","'%s'",image_info->filename); return((Image *) NULL); } blob_info=CloneImageInfo(image_info); blob_info->blob=(void *) blob; blob_info->length=length; if (*blob_info->magick == '\0') (void) SetImageInfo(blob_info,0,exception); magick_info=GetMagickInfo(blob_info->magick,exception); if (magick_info == (const MagickInfo *) NULL) { blob_info=DestroyImageInfo(blob_info); (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'", image_info->filename); return((Image *) NULL); } if (GetMagickBlobSupport(magick_info) != MagickFalse) { /* Native blob support for this image format. */ (void) CopyMagickString(blob_info->filename,image_info->filename, MaxTextExtent); (void) CopyMagickString(blob_info->magick,image_info->magick, MaxTextExtent); image=ReadImage(blob_info,exception); if (image != (Image *) NULL) (void) DetachBlob(image->blob); blob_info=DestroyImageInfo(blob_info); return(image); } /* Write blob to a temporary file on disk. */ blob_info->blob=(void *) NULL; blob_info->length=0; *blob_info->filename='\0'; status=BlobToFile(blob_info->filename,blob,length,exception); if (status == MagickFalse) { (void) RelinquishUniqueFileResource(blob_info->filename); blob_info=DestroyImageInfo(blob_info); return((Image *) NULL); } clone_info=CloneImageInfo(blob_info); (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s", blob_info->magick,blob_info->filename); image=ReadImage(clone_info,exception); if (image != (Image *) NULL) { Image *images; /* Restore original filenames. */ for (images=GetFirstImageInList(image); images != (Image *) NULL; ) { (void) CopyMagickMemory(images->magick_filename,image_info->filename, sizeof(images->magick_filename)); (void) CopyMagickMemory(images->filename,image_info->filename, sizeof(images->filename)); images=GetNextImageInList(images); } } clone_info=DestroyImageInfo(clone_info); (void) RelinquishUniqueFileResource(blob_info->filename); blob_info=DestroyImageInfo(blob_info); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + C l o n e B l o b I n f o % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CloneBlobInfo() makes a duplicate of the given blob info structure, or if % blob info is NULL, a new one. % % The format of the CloneBlobInfo method is: % % BlobInfo *CloneBlobInfo(const BlobInfo *blob_info) % % A description of each parameter follows: % % o blob_info: the blob info. % */ MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info) { BlobInfo *clone_info; clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info)); if (clone_info == (BlobInfo *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); GetBlobInfo(clone_info); if (blob_info == (BlobInfo *) NULL) return(clone_info); clone_info->length=blob_info->length; clone_info->extent=blob_info->extent; clone_info->synchronize=blob_info->synchronize; clone_info->quantum=blob_info->quantum; clone_info->mapped=blob_info->mapped; clone_info->eof=blob_info->eof; clone_info->offset=blob_info->offset; clone_info->size=blob_info->size; clone_info->exempt=blob_info->exempt; clone_info->status=blob_info->status; clone_info->temporary=blob_info->temporary; clone_info->type=blob_info->type; clone_info->file_info.file=blob_info->file_info.file; clone_info->properties=blob_info->properties; clone_info->stream=blob_info->stream; clone_info->data=blob_info->data; clone_info->debug=IsEventLogging(); clone_info->reference_count=1; return(clone_info); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + C l o s e B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CloseBlob() closes a stream associated with the image. % % The format of the CloseBlob method is: % % MagickBooleanType CloseBlob(Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport MagickBooleanType CloseBlob(Image *image) { int status; /* Close image file. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(image->blob != (BlobInfo *) NULL); if (image->blob->type == UndefinedStream) return(MagickTrue); if (image->blob->synchronize != MagickFalse) SyncBlob(image); image->blob->size=GetBlobSize(image); image->extent=image->blob->size; image->blob->eof=MagickFalse; if (image->blob->exempt != MagickFalse) { image->blob->type=UndefinedStream; return(MagickTrue); } status=0; switch (image->blob->type) { case UndefinedStream: case StandardStream: break; case FileStream: case PipeStream: { status=ferror(image->blob->file_info.file); break; } case ZipStream: { #if defined(MAGICKCORE_ZLIB_DELEGATE) (void) gzerror(image->blob->file_info.gzfile,&status); #endif break; } case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) (void) BZ2_bzerror(image->blob->file_info.bzfile,&status); #endif break; } case FifoStream: case BlobStream: break; } image->blob->status=status < 0 ? MagickTrue : MagickFalse; switch (image->blob->type) { case UndefinedStream: case StandardStream: break; case FileStream: { if (image->blob->synchronize != MagickFalse) { status=fflush(image->blob->file_info.file); status=fsync(fileno(image->blob->file_info.file)); } status=fclose(image->blob->file_info.file); break; } case PipeStream: { #if defined(MAGICKCORE_HAVE_PCLOSE) status=pclose(image->blob->file_info.file); #endif break; } case ZipStream: { #if defined(MAGICKCORE_ZLIB_DELEGATE) status=gzclose(image->blob->file_info.gzfile); #endif break; } case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) BZ2_bzclose(image->blob->file_info.bzfile); #endif break; } case FifoStream: break; case BlobStream: { if (image->blob->file_info.file != (FILE *) NULL) { if (image->blob->synchronize != MagickFalse) (void) fsync(fileno(image->blob->file_info.file)); status=fclose(image->blob->file_info.file); } break; } } (void) DetachBlob(image->blob); image->blob->status=status < 0 ? MagickTrue : MagickFalse; return(image->blob->status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + D e s t r o y B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % DestroyBlob() deallocates memory associated with a blob. % % The format of the DestroyBlob method is: % % void DestroyBlob(Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport void DestroyBlob(Image *image) { MagickBooleanType destroy; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->signature == MagickSignature); destroy=MagickFalse; LockSemaphoreInfo(image->blob->semaphore); image->blob->reference_count--; assert(image->blob->reference_count >= 0); if (image->blob->reference_count == 0) destroy=MagickTrue; UnlockSemaphoreInfo(image->blob->semaphore); if (destroy == MagickFalse) return; (void) CloseBlob(image); if (image->blob->mapped != MagickFalse) (void) UnmapBlob(image->blob->data,image->blob->length); if (image->blob->semaphore != (SemaphoreInfo *) NULL) DestroySemaphoreInfo(&image->blob->semaphore); image->blob->signature=(~MagickSignature); image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + D e t a c h B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % DetachBlob() detaches a blob from the BlobInfo structure. % % The format of the DetachBlob method is: % % unsigned char *DetachBlob(BlobInfo *blob_info) % % A description of each parameter follows: % % o blob_info: Specifies a pointer to a BlobInfo structure. % */ MagickExport unsigned char *DetachBlob(BlobInfo *blob_info) { unsigned char *data; assert(blob_info != (BlobInfo *) NULL); if (blob_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); if (blob_info->mapped != MagickFalse) (void) UnmapBlob(blob_info->data,blob_info->length); blob_info->mapped=MagickFalse; blob_info->length=0; blob_info->offset=0; blob_info->eof=MagickFalse; blob_info->exempt=MagickFalse; blob_info->type=UndefinedStream; blob_info->file_info.file=(FILE *) NULL; data=blob_info->data; blob_info->data=(unsigned char *) NULL; blob_info->stream=(StreamHandler) NULL; return(data); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + D i s c a r d B l o b B y t e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % DiscardBlobBytes() discards bytes in a blob. % % The format of the DiscardBlobBytes method is: % % MagickBooleanType DiscardBlobBytes(Image *image,const size_t length) % % A description of each parameter follows. % % o image: the image. % % o length: the number of bytes to skip. % */ static inline const unsigned char *ReadBlobStream(Image *image, const size_t length,unsigned char *data,ssize_t *count) { assert(count != (ssize_t *) NULL); assert(image->blob != (BlobInfo *) NULL); if (image->blob->type != BlobStream) { *count=ReadBlob(image,length,data); return(data); } if (image->blob->offset >= (MagickOffsetType) image->blob->length) { *count=0; image->blob->eof=MagickTrue; return(data); } data=image->blob->data+image->blob->offset; *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length- image->blob->offset)); image->blob->offset+=(*count); if (*count != (ssize_t) length) image->blob->eof=MagickTrue; return(data); } MagickExport MagickBooleanType DiscardBlobBytes(Image *image, const MagickSizeType length) { register MagickOffsetType i; size_t quantum; ssize_t count; unsigned char buffer[16384]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); count=0; for (i=0; i < (MagickOffsetType) length; i+=count) { quantum=(size_t) MagickMin(length-i,sizeof(buffer)); (void) ReadBlobStream(image,quantum,buffer,&count); if (count <= 0) { count=0; if (errno != EINTR) break; } } return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + D u p l i c a t e s B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % DuplicateBlob() duplicates a blob descriptor. % % The format of the DuplicateBlob method is: % % void DuplicateBlob(Image *image,const Image *duplicate) % % A description of each parameter follows: % % o image: the image. % % o duplicate: the duplicate image. % */ MagickExport void DuplicateBlob(Image *image,const Image *duplicate) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(duplicate != (Image *) NULL); assert(duplicate->signature == MagickSignature); DestroyBlob(image); image->blob=ReferenceBlob(duplicate->blob); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + E O F B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % EOFBlob() returns a non-zero value when EOF has been detected reading from % a blob or file. % % The format of the EOFBlob method is: % % int EOFBlob(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport int EOFBlob(const Image *image) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); switch (image->blob->type) { case UndefinedStream: case StandardStream: break; case FileStream: case PipeStream: { image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue : MagickFalse; break; } case ZipStream: { image->blob->eof=MagickFalse; break; } case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) int status; status=0; (void) BZ2_bzerror(image->blob->file_info.bzfile,&status); image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse; #endif break; } case FifoStream: { image->blob->eof=MagickFalse; break; } case BlobStream: break; } return((int) image->blob->eof); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + F i l e T o B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % FileToBlob() returns the contents of a file as a buffer terminated with % the '\0' character. The length of the buffer (not including the extra % terminating '\0' character) is returned via the 'length' parameter. Free % the buffer with RelinquishMagickMemory(). % % The format of the FileToBlob method is: % % unsigned char *FileToBlob(const char *filename,const size_t extent, % size_t *length,ExceptionInfo *exception) % % A description of each parameter follows: % % o blob: FileToBlob() returns the contents of a file as a blob. If % an error occurs NULL is returned. % % o filename: the filename. % % o extent: The maximum length of the blob. % % o length: On return, this reflects the actual length of the blob. % % o exception: return any errors or warnings in this structure. % */ MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent, size_t *length,ExceptionInfo *exception) { int file; MagickOffsetType offset; register size_t i; ssize_t count; unsigned char *blob; void *map; assert(filename != (const char *) NULL); (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); assert(exception != (ExceptionInfo *) NULL); *length=0; file=fileno(stdin); if (LocaleCompare(filename,"-") != 0) file=open_utf8(filename,O_RDONLY | O_BINARY,0); if (file == -1) { ThrowFileException(exception,BlobError,"UnableToOpenFile",filename); return((unsigned char *) NULL); } offset=(MagickOffsetType) lseek(file,0,SEEK_END); count=0; if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset))) { size_t quantum; struct stat file_stats; /* Stream is not seekable. */ quantum=(size_t) MagickMaxBufferExtent; if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0)) quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size, MagickMaxBufferExtent); blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob)); for (i=0; blob != (unsigned char *) NULL; i+=count) { count=(ssize_t) read(file,blob+i,quantum); if (count <= 0) { count=0; if (errno != EINTR) break; } if (~(1UL*i) < (quantum+1)) { blob=(unsigned char *) RelinquishMagickMemory(blob); break; } blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1, sizeof(*blob)); if ((size_t) (i+count) >= extent) break; } if (LocaleCompare(filename,"-") != 0) file=close(file); if (blob == (unsigned char *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","'%s'",filename); return((unsigned char *) NULL); } if (file == -1) { blob=(unsigned char *) RelinquishMagickMemory(blob); ThrowFileException(exception,BlobError,"UnableToReadBlob",filename); return((unsigned char *) NULL); } *length=(size_t) MagickMin(i+count,extent); blob[*length]='\0'; return(blob); } *length=(size_t) MagickMin((MagickSizeType) offset,extent); blob=(unsigned char *) NULL; if (~(*length) >= (MaxTextExtent-1)) blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent, sizeof(*blob)); if (blob == (unsigned char *) NULL) { file=close(file); (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","'%s'",filename); return((unsigned char *) NULL); } map=MapBlob(file,ReadMode,0,*length); if (map != (unsigned char *) NULL) { (void) memcpy(blob,map,*length); (void) UnmapBlob(map,*length); } else { (void) lseek(file,0,SEEK_SET); for (i=0; i < *length; i+=count) { count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i, (MagickSizeType) SSIZE_MAX)); if (count <= 0) { count=0; if (errno != EINTR) break; } } if (i < *length) { file=close(file)-1; blob=(unsigned char *) RelinquishMagickMemory(blob); ThrowFileException(exception,BlobError,"UnableToReadBlob",filename); return((unsigned char *) NULL); } } blob[*length]='\0'; if (LocaleCompare(filename,"-") != 0) file=close(file); if (file == -1) { blob=(unsigned char *) RelinquishMagickMemory(blob); ThrowFileException(exception,BlobError,"UnableToReadBlob",filename); } return(blob); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % F i l e T o I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % FileToImage() write the contents of a file to an image. % % The format of the FileToImage method is: % % MagickBooleanType FileToImage(Image *,const char *filename) % % A description of each parameter follows: % % o image: the image. % % o filename: the filename. % */ static inline ssize_t WriteBlobStream(Image *image,const size_t length, const unsigned char *data) { MagickSizeType extent; register unsigned char *q; assert(image->blob != (BlobInfo *) NULL); if (image->blob->type != BlobStream) return(WriteBlob(image,length,data)); assert(image->blob->type != UndefinedStream); assert(data != (void *) NULL); extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length); if (extent >= image->blob->extent) { image->blob->quantum<<=1; extent=image->blob->extent+image->blob->quantum+length; if (SetBlobExtent(image,extent) == MagickFalse) return(0); } q=image->blob->data+image->blob->offset; (void) memcpy(q,data,length); image->blob->offset+=length; if (image->blob->offset >= (MagickOffsetType) image->blob->length) image->blob->length=(size_t) image->blob->offset; return((ssize_t) length); } MagickExport MagickBooleanType FileToImage(Image *image,const char *filename, ExceptionInfo *exception) { int file; size_t length, quantum; ssize_t count; struct stat file_stats; unsigned char *blob; assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); assert(filename != (const char *) NULL); (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); file=open_utf8(filename,O_RDONLY | O_BINARY,0); if (file == -1) { ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename); return(MagickFalse); } quantum=(size_t) MagickMaxBufferExtent; if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0)) quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent); blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob)); if (blob == (unsigned char *) NULL) { ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed", filename); return(MagickFalse); } for ( ; ; ) { count=(ssize_t) read(file,blob,quantum); if (count <= 0) { count=0; if (errno != EINTR) break; } length=(size_t) count; count=WriteBlobStream(image,length,blob); if (count != (ssize_t) length) { ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); break; } } file=close(file); if (file == -1) ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); blob=(unsigned char *) RelinquishMagickMemory(blob); return(MagickTrue); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + G e t B l o b E r r o r % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetBlobError() returns MagickTrue if the blob associated with the specified % image encountered an error. % % The format of the GetBlobError method is: % % MagickBooleanType GetBlobError(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickPrivate MagickBooleanType GetBlobError(const Image *image) { assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); return(image->blob->status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + G e t B l o b F i l e H a n d l e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetBlobFileHandle() returns the file handle associated with the image blob. % % The format of the GetBlobFile method is: % % FILE *GetBlobFileHandle(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport FILE *GetBlobFileHandle(const Image *image) { assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); return(image->blob->file_info.file); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + G e t B l o b I n f o % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetBlobInfo() initializes the BlobInfo structure. % % The format of the GetBlobInfo method is: % % void GetBlobInfo(BlobInfo *blob_info) % % A description of each parameter follows: % % o blob_info: Specifies a pointer to a BlobInfo structure. % */ MagickPrivate void GetBlobInfo(BlobInfo *blob_info) { assert(blob_info != (BlobInfo *) NULL); (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info)); blob_info->type=UndefinedStream; blob_info->quantum=(size_t) MagickMaxBlobExtent; blob_info->properties.st_mtime=time((time_t *) NULL); blob_info->properties.st_ctime=time((time_t *) NULL); blob_info->debug=IsEventLogging(); blob_info->reference_count=1; blob_info->semaphore=AllocateSemaphoreInfo(); blob_info->signature=MagickSignature; } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G e t B l o b P r o p e r t i e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetBlobProperties() returns information about an image blob. % % The format of the GetBlobProperties method is: % % const struct stat *GetBlobProperties(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickPrivate const struct stat *GetBlobProperties(const Image *image) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); return(&image->blob->properties); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + G e t B l o b S i z e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetBlobSize() returns the current length of the image file or blob; zero is % returned if the size cannot be determined. % % The format of the GetBlobSize method is: % % MagickSizeType GetBlobSize(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport MagickSizeType GetBlobSize(const Image *image) { MagickSizeType extent; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(image->blob != (BlobInfo *) NULL); extent=0; switch (image->blob->type) { case UndefinedStream: { extent=image->blob->size; break; } case StandardStream: { extent=image->blob->size; break; } case FileStream: { if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0) extent=(MagickSizeType) image->blob->properties.st_size; break; } case PipeStream: { extent=image->blob->size; break; } case ZipStream: case BZipStream: { MagickBooleanType status; status=GetPathAttributes(image->filename,&image->blob->properties); if (status != MagickFalse) extent=(MagickSizeType) image->blob->properties.st_size; break; } case FifoStream: break; case BlobStream: { extent=(MagickSizeType) image->blob->length; break; } } return(extent); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + G e t B l o b S t r e a m D a t a % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetBlobStreamData() returns the stream data for the image. % % The format of the GetBlobStreamData method is: % % unsigned char *GetBlobStreamData(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport unsigned char *GetBlobStreamData(const Image *image) { assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); return(image->blob->data); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + G e t B l o b S t r e a m H a n d l e r % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetBlobStreamHandler() returns the stream handler for the image. % % The format of the GetBlobStreamHandler method is: % % StreamHandler GetBlobStreamHandler(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image) { assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); return(image->blob->stream); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % I m a g e T o B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ImageToBlob() implements direct to memory image formats. It returns the % image as a formatted blob and its length. The magick member of the Image % structure determines the format of the returned blob (GIF, JPEG, PNG, % etc.). This method is the equivalent of WriteImage(), but writes the % formatted "file" to a memory buffer rather than to an actual file. % % The format of the ImageToBlob method is: % % unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image, % size_t *length,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o image: the image. % % o length: This pointer to a size_t integer sets the initial length of the % blob. On return, it reflects the actual length of the blob. % % o exception: return any errors or warnings in this structure. % */ MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info, Image *image,size_t *length,ExceptionInfo *exception) { const MagickInfo *magick_info; ImageInfo *blob_info; MagickBooleanType status; unsigned char *blob; assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); *length=0; blob=(unsigned char *) NULL; blob_info=CloneImageInfo(image_info); blob_info->adjoin=MagickFalse; (void) SetImageInfo(blob_info,1,exception); if (*blob_info->magick != '\0') (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent); magick_info=GetMagickInfo(image->magick,exception); if (magick_info == (const MagickInfo *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'", image->filename); return(blob); } (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent); if (GetMagickBlobSupport(magick_info) != MagickFalse) { /* Native blob support for this image format. */ blob_info->length=0; blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent, sizeof(unsigned char)); if (blob_info->blob == (void *) NULL) (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename); else { (void) CloseBlob(image); image->blob->exempt=MagickTrue; *image->filename='\0'; status=WriteImage(blob_info,image,exception); if ((status != MagickFalse) && (image->blob->length != 0)) { *length=image->blob->length; blob=DetachBlob(image->blob); blob=(unsigned char *) ResizeQuantumMemory(blob,*length, sizeof(*blob)); } } } else { char unique[MaxTextExtent]; int file; /* Write file to disk in blob image format. */ file=AcquireUniqueFileResource(unique); if (file == -1) { ThrowFileException(exception,BlobError,"UnableToWriteBlob", image_info->filename); } else { blob_info->file=fdopen(file,"wb"); if (blob_info->file != (FILE *) NULL) { (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s", image->magick,unique); status=WriteImage(blob_info,image,exception); (void) fclose(blob_info->file); if (status != MagickFalse) blob=FileToBlob(image->filename,~0UL,length,exception); } (void) RelinquishUniqueFileResource(unique); } } blob_info=DestroyImageInfo(blob_info); return(blob); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % I m a g e T o F i l e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ImageToFile() writes an image to a file. It returns MagickFalse if an error % occurs otherwise MagickTrue. % % The format of the ImageToFile method is: % % MagickBooleanType ImageToFile(Image *image,char *filename, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o filename: Write the image to this file. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType ImageToFile(Image *image,char *filename, ExceptionInfo *exception) { int file; register const unsigned char *p; register size_t i; size_t length, quantum; ssize_t count; struct stat file_stats; unsigned char *buffer; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); assert(filename != (const char *) NULL); if (*filename == '\0') file=AcquireUniqueFileResource(filename); else if (LocaleCompare(filename,"-") == 0) file=fileno(stdout); else file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE); if (file == -1) { ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); return(MagickFalse); } quantum=(size_t) MagickMaxBufferExtent; if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0)) quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size, MagickMaxBufferExtent); buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer)); if (buffer == (unsigned char *) NULL) { file=close(file)-1; (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationError","'%s'",filename); return(MagickFalse); } length=0; p=ReadBlobStream(image,quantum,buffer,&count); for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count)) { length=(size_t) count; for (i=0; i < length; i+=count) { count=write(file,p+i,(size_t) (length-i)); if (count <= 0) { count=0; if (errno != EINTR) break; } } if (i < length) break; } if (LocaleCompare(filename,"-") != 0) file=close(file); buffer=(unsigned char *) RelinquishMagickMemory(buffer); if ((file == -1) || (i < length)) { ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); return(MagickFalse); } return(MagickTrue); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % I m a g e s T o B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ImagesToBlob() implements direct to memory image formats. It returns the % image sequence as a blob and its length. The magick member of the ImageInfo % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.) % % Note, some image formats do not permit multiple images to the same image % stream (e.g. JPEG). in this instance, just the first image of the % sequence is returned as a blob. % % The format of the ImagesToBlob method is: % % unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images, % size_t *length,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o images: the image list. % % o length: This pointer to a size_t integer sets the initial length of the % blob. On return, it reflects the actual length of the blob. % % o exception: return any errors or warnings in this structure. % */ MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info, Image *images,size_t *length,ExceptionInfo *exception) { const MagickInfo *magick_info; ImageInfo *blob_info; MagickBooleanType status; unsigned char *blob; assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(images != (Image *) NULL); assert(images->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); *length=0; blob=(unsigned char *) NULL; blob_info=CloneImageInfo(image_info); (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images), exception); if (*blob_info->magick != '\0') (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent); if (blob_info->adjoin == MagickFalse) { blob_info=DestroyImageInfo(blob_info); return(ImageToBlob(image_info,images,length,exception)); } magick_info=GetMagickInfo(images->magick,exception); if (magick_info == (const MagickInfo *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'", images->filename); return(blob); } (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent); if (GetMagickBlobSupport(magick_info) != MagickFalse) { /* Native blob support for this images format. */ blob_info->length=0; blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent, sizeof(unsigned char)); if (blob_info->blob == (void *) NULL) (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","'%s'",images->filename); else { images->blob->exempt=MagickTrue; *images->filename='\0'; status=WriteImages(blob_info,images,images->filename,exception); if ((status != MagickFalse) && (images->blob->length != 0)) { *length=images->blob->length; blob=DetachBlob(images->blob); blob=(unsigned char *) ResizeQuantumMemory(blob,*length, sizeof(*blob)); } } } else { char filename[MaxTextExtent], unique[MaxTextExtent]; int file; /* Write file to disk in blob images format. */ file=AcquireUniqueFileResource(unique); if (file == -1) { ThrowFileException(exception,FileOpenError,"UnableToWriteBlob", image_info->filename); } else { blob_info->file=fdopen(file,"wb"); if (blob_info->file != (FILE *) NULL) { (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s", images->magick,unique); status=WriteImages(blob_info,images,filename,exception); (void) fclose(blob_info->file); if (status != MagickFalse) blob=FileToBlob(images->filename,~0UL,length,exception); } (void) RelinquishUniqueFileResource(unique); } } blob_info=DestroyImageInfo(blob_info); return(blob); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % I n j e c t I m a g e B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % InjectImageBlob() injects the image with a copy of itself in the specified % format (e.g. inject JPEG into a PDF image). % % The format of the InjectImageBlob method is: % % MagickBooleanType InjectImageBlob(const ImageInfo *image_info, % Image *image,Image *inject_image,const char *format, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info.. % % o image: the image. % % o inject_image: inject into the image stream. % % o format: the image format. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info, Image *image,Image *inject_image,const char *format,ExceptionInfo *exception) { char filename[MaxTextExtent]; FILE *unique_file; Image *byte_image; ImageInfo *write_info; int file; MagickBooleanType status; register ssize_t i; size_t quantum; ssize_t count; struct stat file_stats; unsigned char *buffer; /* Write inject image to a temporary file. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(inject_image != (Image *) NULL); assert(inject_image->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); unique_file=(FILE *) NULL; file=AcquireUniqueFileResource(filename); if (file != -1) unique_file=fdopen(file,"wb"); if ((file == -1) || (unique_file == (FILE *) NULL)) { (void) CopyMagickString(image->filename,filename,MaxTextExtent); ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", image->filename); return(MagickFalse); } byte_image=CloneImage(inject_image,0,0,MagickFalse,exception); if (byte_image == (Image *) NULL) { (void) fclose(unique_file); (void) RelinquishUniqueFileResource(filename); return(MagickFalse); } (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format, filename); DestroyBlob(byte_image); byte_image->blob=CloneBlobInfo((BlobInfo *) NULL); write_info=CloneImageInfo(image_info); SetImageInfoFile(write_info,unique_file); status=WriteImage(write_info,byte_image,exception); write_info=DestroyImageInfo(write_info); byte_image=DestroyImage(byte_image); (void) fclose(unique_file); if (status == MagickFalse) { (void) RelinquishUniqueFileResource(filename); return(MagickFalse); } /* Inject into image stream. */ file=open_utf8(filename,O_RDONLY | O_BINARY,0); if (file == -1) { (void) RelinquishUniqueFileResource(filename); ThrowFileException(exception,FileOpenError,"UnableToOpenFile", image_info->filename); return(MagickFalse); } quantum=(size_t) MagickMaxBufferExtent; if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0)) quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent); buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer)); if (buffer == (unsigned char *) NULL) { (void) RelinquishUniqueFileResource(filename); ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } for (i=0; ; i+=count) { count=(ssize_t) read(file,buffer,quantum); if (count <= 0) { count=0; if (errno != EINTR) break; } status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue : MagickFalse; } file=close(file); if (file == -1) ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename); (void) RelinquishUniqueFileResource(filename); buffer=(unsigned char *) RelinquishMagickMemory(buffer); return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + I s B l o b E x e m p t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % IsBlobExempt() returns true if the blob is exempt. % % The format of the IsBlobExempt method is: % % MagickBooleanType IsBlobExempt(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickPrivate MagickBooleanType IsBlobExempt(const Image *image) { assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); return(image->blob->exempt); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + I s B l o b S e e k a b l e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % IsBlobSeekable() returns true if the blob is seekable. % % The format of the IsBlobSeekable method is: % % MagickBooleanType IsBlobSeekable(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image) { MagickBooleanType seekable; assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); switch (image->blob->type) { case FileStream: case BlobStream: case ZipStream: { seekable=MagickTrue; break; } default: { seekable=MagickFalse; break; } } return(seekable); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + I s B l o b T e m p o r a r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % IsBlobTemporary() returns true if the blob is temporary. % % The format of the IsBlobTemporary method is: % % MagickBooleanType IsBlobTemporary(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image) { assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); return(image->blob->temporary); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + M a p B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % MapBlob() creates a mapping from a file to a binary large object. % % The format of the MapBlob method is: % % unsigned char *MapBlob(int file,const MapMode mode, % const MagickOffsetType offset,const size_t length) % % A description of each parameter follows: % % o file: map this file descriptor. % % o mode: ReadMode, WriteMode, or IOMode. % % o offset: starting at this offset within the file. % % o length: the length of the mapping is returned in this pointer. % */ MagickExport unsigned char *MapBlob(int file,const MapMode mode, const MagickOffsetType offset,const size_t length) { #if defined(MAGICKCORE_HAVE_MMAP_FILEIO) int flags, protection; unsigned char *map; /* Map file. */ flags=0; if (file == -1) #if defined(MAP_ANONYMOUS) flags|=MAP_ANONYMOUS; #else return((unsigned char *) NULL); #endif switch (mode) { case ReadMode: default: { protection=PROT_READ; flags|=MAP_PRIVATE; map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file, (off_t) offset); break; } case WriteMode: { protection=PROT_WRITE; flags|=MAP_SHARED; map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file, (off_t) offset); #if defined(MAGICKCORE_HAVE_POSIX_MADVISE) (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED); #endif break; } case IOMode: { protection=PROT_READ | PROT_WRITE; flags|=MAP_SHARED; map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file, (off_t) offset); break; } } if (map == (unsigned char *) MAP_FAILED) return((unsigned char *) NULL); return(map); #else (void) file; (void) mode; (void) offset; (void) length; return((unsigned char *) NULL); #endif } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + M S B O r d e r L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % MSBOrderLong() converts a least-significant byte first buffer of integers to % most-significant byte first. % % The format of the MSBOrderLong method is: % % void MSBOrderLong(unsigned char *buffer,const size_t length) % % A description of each parameter follows. % % o buffer: Specifies a pointer to a buffer of integers. % % o length: Specifies the length of the buffer. % */ MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length) { int c; register unsigned char *p, *q; assert(buffer != (unsigned char *) NULL); q=buffer+length; while (buffer < q) { p=buffer+3; c=(int) (*p); *p=(*buffer); *buffer++=(unsigned char) c; p=buffer+1; c=(int) (*p); *p=(*buffer); *buffer++=(unsigned char) c; buffer+=2; } } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + M S B O r d e r S h o r t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % MSBOrderShort() converts a least-significant byte first buffer of integers % to most-significant byte first. % % The format of the MSBOrderShort method is: % % void MSBOrderShort(unsigned char *p,const size_t length) % % A description of each parameter follows. % % o p: Specifies a pointer to a buffer of integers. % % o length: Specifies the length of the buffer. % */ MagickExport void MSBOrderShort(unsigned char *p,const size_t length) { int c; register unsigned char *q; assert(p != (unsigned char *) NULL); q=p+length; while (p < q) { c=(int) (*p); *p=(*(p+1)); p++; *p++=(unsigned char) c; } } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + O p e n B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % OpenBlob() opens a file associated with the image. A file name of '-' sets % the file to stdin for type 'r' and stdout for type 'w'. If the filename % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and % compressed for type 'w'. If the filename prefix is '|', it is piped to or % from a system command. % % The format of the OpenBlob method is: % % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image, % const BlobMode mode,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o image: the image. % % o mode: the mode for opening the file. % */ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info, Image *image,const BlobMode mode,ExceptionInfo *exception) { char extension[MaxTextExtent], filename[MaxTextExtent]; const char *type; MagickBooleanType status; PolicyRights rights; assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image_info->blob != (void *) NULL) { if (image_info->stream != (StreamHandler) NULL) image->blob->stream=(StreamHandler) image_info->stream; AttachBlob(image->blob,image_info->blob,image_info->length); return(MagickTrue); } (void) DetachBlob(image->blob); switch (mode) { default: type="r"; break; case ReadBlobMode: type="r"; break; case ReadBinaryBlobMode: type="rb"; break; case WriteBlobMode: type="w"; break; case WriteBinaryBlobMode: type="w+b"; break; case AppendBlobMode: type="a"; break; case AppendBinaryBlobMode: type="a+b"; break; } if (*type != 'r') image->blob->synchronize=image_info->synchronize; if (image_info->stream != (StreamHandler) NULL) { image->blob->stream=(StreamHandler) image_info->stream; if (*type == 'w') { image->blob->type=FifoStream; return(MagickTrue); } } /* Open image file. */ *filename='\0'; (void) CopyMagickString(filename,image->filename,MaxTextExtent); rights=ReadPolicyRights; if (*type == 'w') rights=WritePolicyRights; if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse) { errno=EPERM; (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, "NotAuthorized","'%s'",filename); return(MagickFalse); } if ((LocaleCompare(filename,"-") == 0) || ((*filename == '\0') && (image_info->file == (FILE *) NULL))) { image->blob->file_info.file=(*type == 'r') ? stdin : stdout; #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) if (strchr(type,'b') != (char *) NULL) setmode(_fileno(image->blob->file_info.file),_O_BINARY); #endif image->blob->type=StandardStream; image->blob->exempt=MagickTrue; return(MagickTrue); } if (LocaleNCompare(filename,"fd:",3) == 0) { char mode[MaxTextExtent]; *mode=(*type); mode[1]='\0'; image->blob->file_info.file=fdopen(StringToLong(filename+3),mode); #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) if (strchr(type,'b') != (char *) NULL) setmode(_fileno(image->blob->file_info.file),_O_BINARY); #endif image->blob->type=StandardStream; image->blob->exempt=MagickTrue; return(MagickTrue); } #if defined(MAGICKCORE_HAVE_POPEN) if (*filename == '|') { char mode[MaxTextExtent]; /* Pipe image to or from a system command. */ #if defined(SIGPIPE) if (*type == 'w') (void) signal(SIGPIPE,SIG_IGN); #endif *mode=(*type); mode[1]='\0'; image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode); if (image->blob->file_info.file == (FILE *) NULL) { ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename); return(MagickFalse); } image->blob->type=PipeStream; image->blob->exempt=MagickTrue; return(MagickTrue); } #endif status=GetPathAttributes(filename,&image->blob->properties); #if defined(S_ISFIFO) if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode)) { image->blob->file_info.file=(FILE *) fopen_utf8(filename,type); if (image->blob->file_info.file == (FILE *) NULL) { ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename); return(MagickFalse); } image->blob->type=FileStream; image->blob->exempt=MagickTrue; return(MagickTrue); } #endif GetPathComponent(image->filename,ExtensionPath,extension); if (*type == 'w') { (void) CopyMagickString(filename,image->filename,MaxTextExtent); if ((image_info->adjoin == MagickFalse) || (strchr(filename,'%') != (char *) NULL)) { /* Form filename for multi-part images. */ (void) InterpretImageFilename(image_info,image,image->filename,(int) image->scene,filename,exception); if ((LocaleCompare(filename,image->filename) == 0) && ((GetPreviousImageInList(image) != (Image *) NULL) || (GetNextImageInList(image) != (Image *) NULL))) { char path[MaxTextExtent]; GetPathComponent(image->filename,RootPath,path); if (*extension == '\0') (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g", path,(double) image->scene); else (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s", path,(double) image->scene,extension); } (void) CopyMagickString(image->filename,filename,MaxTextExtent); #if defined(macintosh) SetApplicationType(filename,image_info->magick,'8BIM'); #endif } } if (image_info->file != (FILE *) NULL) { image->blob->file_info.file=image_info->file; image->blob->type=FileStream; image->blob->exempt=MagickTrue; } else if (*type == 'r') { image->blob->file_info.file=(FILE *) fopen_utf8(filename,type); if (image->blob->file_info.file != (FILE *) NULL) { size_t count; unsigned char magick[3]; image->blob->type=FileStream; #if defined(MAGICKCORE_HAVE_SETVBUF) (void) setvbuf(image->blob->file_info.file,(char *) NULL, (int) _IOFBF,16384); #endif (void) ResetMagickMemory(magick,0,sizeof(magick)); count=fread(magick,1,sizeof(magick),image->blob->file_info.file); (void) rewind(image->blob->file_info.file); (void) LogMagickEvent(BlobEvent,GetMagickModule(), " read %.20g magic header bytes",(double) count); #if defined(MAGICKCORE_ZLIB_DELEGATE) if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) && ((int) magick[2] == 0x08)) { (void) fclose(image->blob->file_info.file); image->blob->file_info.gzfile=gzopen(filename,type); if (image->blob->file_info.gzfile != (gzFile) NULL) image->blob->type=ZipStream; } #endif #if defined(MAGICKCORE_BZLIB_DELEGATE) if (strncmp((char *) magick,"BZh",3) == 0) { (void) fclose(image->blob->file_info.file); image->blob->file_info.bzfile=BZ2_bzopen(filename,type); if (image->blob->file_info.bzfile != (BZFILE *) NULL) image->blob->type=BZipStream; } #endif if (image->blob->type == FileStream) { const MagickInfo *magick_info; ExceptionInfo *sans_exception; struct stat *properties; sans_exception=AcquireExceptionInfo(); magick_info=GetMagickInfo(image_info->magick,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); properties=(&image->blob->properties); if ((magick_info != (const MagickInfo *) NULL) && (GetMagickBlobSupport(magick_info) != MagickFalse) && (properties->st_size <= MagickMaxBufferExtent)) { size_t length; void *blob; length=(size_t) properties->st_size; blob=MapBlob(fileno(image->blob->file_info.file),ReadMode, 0,length); if (blob != (void *) NULL) { /* Format supports blobs-- use memory-mapped I/O. */ if (image_info->file != (FILE *) NULL) image->blob->exempt=MagickFalse; else { (void) fclose(image->blob->file_info.file); image->blob->file_info.file=(FILE *) NULL; } AttachBlob(image->blob,blob,length); image->blob->mapped=MagickTrue; } } } } } else #if defined(MAGICKCORE_ZLIB_DELEGATE) if ((LocaleCompare(extension,"Z") == 0) || (LocaleCompare(extension,"gz") == 0) || (LocaleCompare(extension,"wmz") == 0) || (LocaleCompare(extension,"svgz") == 0)) { if (mode == WriteBinaryBlobMode) type="wb"; image->blob->file_info.gzfile=gzopen(filename,type); if (image->blob->file_info.gzfile != (gzFile) NULL) image->blob->type=ZipStream; } else #endif #if defined(MAGICKCORE_BZLIB_DELEGATE) if (LocaleCompare(extension,"bz2") == 0) { image->blob->file_info.bzfile=BZ2_bzopen(filename,type); if (image->blob->file_info.bzfile != (BZFILE *) NULL) image->blob->type=BZipStream; } else #endif { image->blob->file_info.file=(FILE *) fopen_utf8(filename,type); if (image->blob->file_info.file != (FILE *) NULL) { image->blob->type=FileStream; #if defined(MAGICKCORE_HAVE_SETVBUF) (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int) _IOFBF, 16384); #endif } } image->blob->status=MagickFalse; if (image->blob->type != UndefinedStream) image->blob->size=GetBlobSize(image); else { ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename); return(MagickFalse); } return(MagickTrue); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + P i n g B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % PingBlob() returns all the attributes of an image or image sequence except % for the pixels. It is much faster and consumes far less memory than % BlobToImage(). On failure, a NULL image is returned and exception % describes the reason for the failure. % % The format of the PingBlob method is: % % Image *PingBlob(const ImageInfo *image_info,const void *blob, % const size_t length,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o blob: the address of a character stream in one of the image formats % understood by ImageMagick. % % o length: This size_t integer reflects the length in bytes of the blob. % % o exception: return any errors or warnings in this structure. % */ #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static size_t PingStream(const Image *magick_unused(image), const void *magick_unused(pixels),const size_t columns) { return(columns); } #if defined(__cplusplus) || defined(c_plusplus) } #endif MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob, const size_t length,ExceptionInfo *exception) { Image *image; ImageInfo *ping_info; assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); if ((blob == (const void *) NULL) || (length == 0)) { (void) ThrowMagickException(exception,GetMagickModule(),BlobError, "UnrecognizedImageFormat","'%s'",image_info->magick); return((Image *) NULL); } ping_info=CloneImageInfo(image_info); ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char)); if (ping_info->blob == (const void *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitFatalError,"MemoryAllocationFailed","'%s'",""); return((Image *) NULL); } (void) memcpy(ping_info->blob,blob,length); ping_info->length=length; ping_info->ping=MagickTrue; image=ReadStream(ping_info,&PingStream,exception); ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob); ping_info=DestroyImageInfo(ping_info); return(image); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlob() reads data from the blob or image file and returns it. It % returns the number of bytes read. % % The format of the ReadBlob method is: % % ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data) % % A description of each parameter follows: % % o image: the image. % % o length: Specifies an integer representing the number of bytes to read % from the file. % % o data: Specifies an area to place the information requested from the % file. % */ MagickExport ssize_t ReadBlob(Image *image,const size_t length, unsigned char *data) { int c; register unsigned char *q; ssize_t count; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); if (length == 0) return(0); assert(data != (void *) NULL); count=0; q=data; switch (image->blob->type) { case UndefinedStream: break; case StandardStream: { count=(ssize_t) read(fileno(image->blob->file_info.file),q,length); break; } case FileStream: case PipeStream: { switch (length) { default: { count=(ssize_t) fread(q,1,length,image->blob->file_info.file); break; } case 2: { c=getc(image->blob->file_info.file); if (c == EOF) break; *q++=(unsigned char) c; count++; } case 1: { c=getc(image->blob->file_info.file); if (c == EOF) break; *q++=(unsigned char) c; count++; } case 0: break; } break; } case ZipStream: { #if defined(MAGICKCORE_ZLIB_DELEGATE) switch (length) { default: { count=(ssize_t) gzread(image->blob->file_info.gzfile,q, (unsigned int) length); break; } case 2: { c=gzgetc(image->blob->file_info.gzfile); if (c == EOF) break; *q++=(unsigned char) c; count++; } case 1: { c=gzgetc(image->blob->file_info.gzfile); if (c == EOF) break; *q++=(unsigned char) c; count++; } case 0: break; } #endif break; } case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q, (int) length); #endif break; } case FifoStream: break; case BlobStream: { register const unsigned char *p; if (image->blob->offset >= (MagickOffsetType) image->blob->length) { image->blob->eof=MagickTrue; break; } p=image->blob->data+image->blob->offset; count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length- image->blob->offset)); image->blob->offset+=count; if (count != (ssize_t) length) image->blob->eof=MagickTrue; (void) memcpy(q,p,(size_t) count); break; } } return(count); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b B y t e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobByte() reads a single byte from the image file and returns it. % % The format of the ReadBlobByte method is: % % int ReadBlobByte(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport int ReadBlobByte(Image *image) { register const unsigned char *p; ssize_t count; unsigned char buffer[1]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); p=ReadBlobStream(image,1,buffer,&count); if (count != 1) return(EOF); return((int) (*p)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b D o u b l e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order % specified by the endian member of the image structure. % % The format of the ReadBlobDouble method is: % % double ReadBlobDouble(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport double ReadBlobDouble(Image *image) { union { MagickSizeType unsigned_value; double double_value; } quantum; quantum.double_value=0.0; quantum.unsigned_value=ReadBlobLongLong(image); return(quantum.double_value); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b F l o a t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order % specified by the endian member of the image structure. % % The format of the ReadBlobFloat method is: % % float ReadBlobFloat(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport float ReadBlobFloat(Image *image) { union { unsigned int unsigned_value; float float_value; } quantum; quantum.float_value=0.0; quantum.unsigned_value=ReadBlobLong(image); return(quantum.float_value); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order % specified by the endian member of the image structure. % % The format of the ReadBlobLong method is: % % unsigned int ReadBlobLong(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport unsigned int ReadBlobLong(Image *image) { register const unsigned char *p; ssize_t count; unsigned char buffer[4]; unsigned int value; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,4,buffer,&count); if (count != 4) return(0UL); if (image->endian == LSBEndian) { value=(unsigned int) (*p++); value|=((unsigned int) (*p++)) << 8; value|=((unsigned int) (*p++)) << 16; value|=((unsigned int) (*p++)) << 24; return(value); } value=((unsigned int) (*p++)) << 24; value|=((unsigned int) (*p++)) << 16; value|=((unsigned int) (*p++)) << 8; value|=((unsigned int) (*p++)); return(value); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b L o n g L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the % byte-order specified by the endian member of the image structure. % % The format of the ReadBlobLongLong method is: % % MagickSizeType ReadBlobLongLong(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport MagickSizeType ReadBlobLongLong(Image *image) { MagickSizeType value; register const unsigned char *p; ssize_t count; unsigned char buffer[8]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,8,buffer,&count); if (count != 8) return(MagickULLConstant(0)); if (image->endian == LSBEndian) { value=(MagickSizeType) (*p++); value|=((MagickSizeType) (*p++)) << 8; value|=((MagickSizeType) (*p++)) << 16; value|=((MagickSizeType) (*p++)) << 24; value|=((MagickSizeType) (*p++)) << 32; value|=((MagickSizeType) (*p++)) << 40; value|=((MagickSizeType) (*p++)) << 48; value|=((MagickSizeType) (*p++)) << 56; return(value & MagickULLConstant(0xffffffffffffffff)); } value=((MagickSizeType) (*p++)) << 56; value|=((MagickSizeType) (*p++)) << 48; value|=((MagickSizeType) (*p++)) << 40; value|=((MagickSizeType) (*p++)) << 32; value|=((MagickSizeType) (*p++)) << 24; value|=((MagickSizeType) (*p++)) << 16; value|=((MagickSizeType) (*p++)) << 8; value|=((MagickSizeType) (*p++)); return(value & MagickULLConstant(0xffffffffffffffff)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b S h o r t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order % specified by the endian member of the image structure. % % The format of the ReadBlobShort method is: % % unsigned short ReadBlobShort(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport unsigned short ReadBlobShort(Image *image) { register const unsigned char *p; register unsigned int value; ssize_t count; unsigned char buffer[2]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,2,buffer,&count); if (count != 2) return((unsigned short) 0U); if (image->endian == LSBEndian) { value=(unsigned int) (*p++); value|=((unsigned int) (*p++)) << 8; return((unsigned short) (value & 0xffff)); } value=(unsigned int) ((*p++) << 8); value|=(unsigned int) (*p++); return((unsigned short) (value & 0xffff)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b L S B L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in % least-significant byte first order. % % The format of the ReadBlobLSBLong method is: % % unsigned int ReadBlobLSBLong(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport unsigned int ReadBlobLSBLong(Image *image) { register const unsigned char *p; register unsigned int value; ssize_t count; unsigned char buffer[4]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,4,buffer,&count); if (count != 4) return(0U); value=(unsigned int) (*p++); value|=((unsigned int) (*p++)) << 8; value|=((unsigned int) (*p++)) << 16; value|=((unsigned int) (*p++)) << 24; return(value); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b L S B S h o r t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobLSBShort() reads a short value as a 16-bit quantity in % least-significant byte first order. % % The format of the ReadBlobLSBShort method is: % % unsigned short ReadBlobLSBShort(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport unsigned short ReadBlobLSBShort(Image *image) { register const unsigned char *p; register unsigned int value; ssize_t count; unsigned char buffer[2]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,2,buffer,&count); if (count != 2) return((unsigned short) 0U); value=(unsigned int) (*p++); value|=((unsigned int) ((*p++)) << 8); return((unsigned short) (value & 0xffff)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b M S B L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in % most-significant byte first order. % % The format of the ReadBlobMSBLong method is: % % unsigned int ReadBlobMSBLong(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport unsigned int ReadBlobMSBLong(Image *image) { register const unsigned char *p; register unsigned int value; ssize_t count; unsigned char buffer[4]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,4,buffer,&count); if (count != 4) return(0UL); value=((unsigned int) (*p++) << 24); value|=((unsigned int) (*p++) << 16); value|=((unsigned int) (*p++) << 8); value|=(unsigned int) (*p++); return(value); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b M S B L o n g L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in % most-significant byte first order. % % The format of the ReadBlobMSBLongLong method is: % % unsigned int ReadBlobMSBLongLong(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image) { register const unsigned char *p; register MagickSizeType value; ssize_t count; unsigned char buffer[8]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,8,buffer,&count); if (count != 8) return(MagickULLConstant(0)); value=((MagickSizeType) (*p++)) << 56; value|=((MagickSizeType) (*p++)) << 48; value|=((MagickSizeType) (*p++)) << 40; value|=((MagickSizeType) (*p++)) << 32; value|=((MagickSizeType) (*p++)) << 24; value|=((MagickSizeType) (*p++)) << 16; value|=((MagickSizeType) (*p++)) << 8; value|=((MagickSizeType) (*p++)); return(value & MagickULLConstant(0xffffffffffffffff)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b M S B S h o r t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobMSBShort() reads a short value as a 16-bit quantity in % most-significant byte first order. % % The format of the ReadBlobMSBShort method is: % % unsigned short ReadBlobMSBShort(Image *image) % % A description of each parameter follows. % % o image: the image. % */ MagickExport unsigned short ReadBlobMSBShort(Image *image) { register const unsigned char *p; register unsigned int value; ssize_t count; unsigned char buffer[2]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); *buffer='\0'; p=ReadBlobStream(image,2,buffer,&count); if (count != 2) return((unsigned short) 0U); value=(unsigned int) ((*p++) << 8); value|=(unsigned int) (*p++); return((unsigned short) (value & 0xffff)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e a d B l o b S t r i n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadBlobString() reads characters from a blob or file until a newline % character is read or an end-of-file condition is encountered. % % The format of the ReadBlobString method is: % % char *ReadBlobString(Image *image,char *string) % % A description of each parameter follows: % % o image: the image. % % o string: the address of a character buffer. % */ MagickExport char *ReadBlobString(Image *image,char *string) { register const unsigned char *p; register ssize_t i; ssize_t count; unsigned char buffer[1]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); for (i=0; i < (MaxTextExtent-1L); i++) { p=ReadBlobStream(image,1,buffer,&count); if (count != 1) { if (i == 0) return((char *) NULL); break; } string[i]=(char) (*p); if ((string[i] == '\r') || (string[i] == '\n')) break; } if (string[i] == '\r') (void) ReadBlobStream(image,1,buffer,&count); string[i]='\0'; return(string); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + R e f e r e n c e B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReferenceBlob() increments the reference count associated with the pixel % blob returning a pointer to the blob. % % The format of the ReferenceBlob method is: % % BlobInfo ReferenceBlob(BlobInfo *blob_info) % % A description of each parameter follows: % % o blob_info: the blob_info. % */ MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob) { assert(blob != (BlobInfo *) NULL); assert(blob->signature == MagickSignature); if (blob->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); LockSemaphoreInfo(blob->semaphore); blob->reference_count++; UnlockSemaphoreInfo(blob->semaphore); return(blob); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + S e e k B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SeekBlob() sets the offset in bytes from the beginning of a blob or file % and returns the resulting offset. % % The format of the SeekBlob method is: % % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset, % const int whence) % % A description of each parameter follows: % % o image: the image. % % o offset: Specifies an integer representing the offset in bytes. % % o whence: Specifies an integer representing how the offset is % treated relative to the beginning of the blob as follows: % % SEEK_SET Set position equal to offset bytes. % SEEK_CUR Set position to current location plus offset. % SEEK_END Set position to EOF plus offset. % */ MagickExport MagickOffsetType SeekBlob(Image *image, const MagickOffsetType offset,const int whence) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); switch (image->blob->type) { case UndefinedStream: break; case StandardStream: return(-1); case FileStream: { if (fseek(image->blob->file_info.file,offset,whence) < 0) return(-1); image->blob->offset=TellBlob(image); break; } case PipeStream: case ZipStream: { #if defined(MAGICKCORE_ZLIB_DELEGATE) if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0) return(-1); #endif image->blob->offset=TellBlob(image); break; } case BZipStream: return(-1); case FifoStream: return(-1); case BlobStream: { switch (whence) { case SEEK_SET: default: { if (offset < 0) return(-1); image->blob->offset=offset; break; } case SEEK_CUR: { if ((image->blob->offset+offset) < 0) return(-1); image->blob->offset+=offset; break; } case SEEK_END: { if (((MagickOffsetType) image->blob->length+offset) < 0) return(-1); image->blob->offset=image->blob->length+offset; break; } } if (image->blob->offset <= (MagickOffsetType) ((off_t) image->blob->length)) image->blob->eof=MagickFalse; else if (image->blob->mapped != MagickFalse) return(-1); else { image->blob->extent=(size_t) (image->blob->offset+ image->blob->quantum); image->blob->data=(unsigned char *) ResizeQuantumMemory( image->blob->data,image->blob->extent+1, sizeof(*image->blob->data)); (void) SyncBlob(image); if (image->blob->data == (unsigned char *) NULL) { (void) DetachBlob(image->blob); return(-1); } } break; } } return(image->blob->offset); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + S e t B l o b E x e m p t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SetBlobExempt() sets the blob exempt status. % % The format of the SetBlobExempt method is: % % MagickBooleanType SetBlobExempt(const Image *image, % const MagickBooleanType exempt) % % A description of each parameter follows: % % o image: the image. % % o exempt: Set to true if this blob is exempt from being closed. % */ MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt) { assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); image->blob->exempt=exempt; } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + S e t B l o b E x t e n t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SetBlobExtent() ensures enough space is allocated for the blob. If the % method is successful, subsequent writes to bytes in the specified range are % guaranteed not to fail. % % The format of the SetBlobExtent method is: % % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent) % % A description of each parameter follows: % % o image: the image. % % o extent: the blob maximum extent. % */ MagickPrivate MagickBooleanType SetBlobExtent(Image *image, const MagickSizeType extent) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); switch (image->blob->type) { case UndefinedStream: break; case StandardStream: return(MagickFalse); case FileStream: { if (extent != (MagickSizeType) ((off_t) extent)) return(MagickFalse); #if !defined(MAGICKCORE_POSIX_FALLOCATE) return(MagickFalse); #else { int status; MagickOffsetType offset; offset=TellBlob(image); status=posix_fallocate(fileno(image->blob->file_info.file), (off_t) offset,(off_t) (extent-offset)); if (status != 0) return(MagickFalse); } #endif break; } case PipeStream: case ZipStream: return(MagickFalse); case BZipStream: return(MagickFalse); case FifoStream: return(MagickFalse); case BlobStream: { if (image->blob->mapped != MagickFalse) { if (image->blob->file_info.file == (FILE *) NULL) return(MagickFalse); (void) UnmapBlob(image->blob->data,image->blob->length); #if !defined(MAGICKCORE_POSIX_FALLOCATE) return(MagickFalse); #else { int status; MagickOffsetType offset; offset=TellBlob(image); status=posix_fallocate(fileno(image->blob->file_info.file), (off_t) offset,(off_t) (extent-offset)); if (status != 0) return(MagickFalse); } image->blob->data=(unsigned char*) MapBlob(fileno( image->blob->file_info.file),WriteMode,0,(size_t) extent); image->blob->extent=(size_t) extent; image->blob->length=(size_t) extent; (void) SyncBlob(image); break; #endif } if (extent != (MagickSizeType) ((size_t) extent)) return(MagickFalse); image->blob->extent=(size_t) extent; image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data, image->blob->extent+1,sizeof(*image->blob->data)); (void) SyncBlob(image); if (image->blob->data == (unsigned char *) NULL) { (void) DetachBlob(image->blob); return(MagickFalse); } break; } } return(MagickTrue); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + S y n c B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SyncBlob() flushes the datastream if it is a file or synchronizes the data % attributes if it is an blob. % % The format of the SyncBlob method is: % % int SyncBlob(Image *image) % % A description of each parameter follows: % % o image: the image. % */ static int SyncBlob(Image *image) { int status; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); status=0; switch (image->blob->type) { case UndefinedStream: case StandardStream: break; case FileStream: case PipeStream: { status=fflush(image->blob->file_info.file); break; } case ZipStream: { #if defined(MAGICKCORE_ZLIB_DELEGATE) status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH); #endif break; } case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) status=BZ2_bzflush(image->blob->file_info.bzfile); #endif break; } case FifoStream: break; case BlobStream: { #if defined(MAGICKCORE_HAVE_MMAP_FILEIO) if (image->blob->mapped != MagickFalse) status=msync(image->blob->data,image->blob->length,MS_SYNC); #endif break; } } return(status); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + T e l l B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % TellBlob() obtains the current value of the blob or file position. % % The format of the TellBlob method is: % % MagickOffsetType TellBlob(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport MagickOffsetType TellBlob(const Image *image) { MagickOffsetType offset; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); offset=(-1); switch (image->blob->type) { case UndefinedStream: case StandardStream: break; case FileStream: { offset=ftell(image->blob->file_info.file); break; } case PipeStream: break; case ZipStream: { #if defined(MAGICKCORE_ZLIB_DELEGATE) offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile); #endif break; } case BZipStream: break; case FifoStream: break; case BlobStream: { offset=image->blob->offset; break; } } return(offset); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + U n m a p B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % UnmapBlob() deallocates the binary large object previously allocated with % the MapBlob method. % % The format of the UnmapBlob method is: % % MagickBooleanType UnmapBlob(void *map,const size_t length) % % A description of each parameter follows: % % o map: the address of the binary large object. % % o length: the length of the binary large object. % */ MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length) { #if defined(MAGICKCORE_HAVE_MMAP_FILEIO) int status; status=munmap(map,length); return(status == -1 ? MagickFalse : MagickTrue); #else (void) map; (void) length; return(MagickFalse); #endif } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlob() writes data to a blob or image file. It returns the number of % bytes written. % % The format of the WriteBlob method is: % % ssize_t WriteBlob(Image *image,const size_t length, % const unsigned char *data) % % A description of each parameter follows: % % o image: the image. % % o length: Specifies an integer representing the number of bytes to % write to the file. % % o data: The address of the data to write to the blob or file. % */ MagickExport ssize_t WriteBlob(Image *image,const size_t length, const unsigned char *data) { int c; register const unsigned char *p; ssize_t count; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(data != (const unsigned char *) NULL); assert(image->blob != (BlobInfo *) NULL); assert(image->blob->type != UndefinedStream); if (length == 0) return(0); count=0; p=data; switch (image->blob->type) { case UndefinedStream: break; case StandardStream: { count=(ssize_t) write(fileno(image->blob->file_info.file),data,length); break; } case FileStream: case PipeStream: { switch (length) { default: { count=(ssize_t) fwrite((const char *) data,1,length, image->blob->file_info.file); break; } case 2: { c=putc((int) *p++,image->blob->file_info.file); if (c == EOF) break; count++; } case 1: { c=putc((int) *p++,image->blob->file_info.file); if (c == EOF) break; count++; } case 0: break; } break; } case ZipStream: { #if defined(MAGICKCORE_ZLIB_DELEGATE) switch (length) { default: { count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data, (unsigned int) length); break; } case 2: { c=gzputc(image->blob->file_info.gzfile,(int) *p++); if (c == EOF) break; count++; } case 1: { c=gzputc(image->blob->file_info.gzfile,(int) *p++); if (c == EOF) break; count++; } case 0: break; } #endif break; } case BZipStream: { #if defined(MAGICKCORE_BZLIB_DELEGATE) count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data, (int) length); #endif break; } case FifoStream: { count=(ssize_t) image->blob->stream(image,data,length); break; } case BlobStream: { register unsigned char *q; if ((image->blob->offset+(MagickOffsetType) length) >= (MagickOffsetType) image->blob->extent) { if (image->blob->mapped != MagickFalse) return(0); image->blob->quantum<<=1; image->blob->extent+=length+image->blob->quantum; image->blob->data=(unsigned char *) ResizeQuantumMemory( image->blob->data,image->blob->extent+1,sizeof(*image->blob->data)); (void) SyncBlob(image); if (image->blob->data == (unsigned char *) NULL) { (void) DetachBlob(image->blob); return(0); } } q=image->blob->data+image->blob->offset; (void) memcpy(q,p,length); image->blob->offset+=length; if (image->blob->offset >= (MagickOffsetType) image->blob->length) image->blob->length=(size_t) image->blob->offset; count=(ssize_t) length; } } return(count); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b B y t e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobByte() write an integer to a blob. It returns the number of bytes % written (either 0 or 1); % % The format of the WriteBlobByte method is: % % ssize_t WriteBlobByte(Image *image,const unsigned char value) % % A description of each parameter follows. % % o image: the image. % % o value: Specifies the value to write. % */ MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); return(WriteBlobStream(image,1,&value)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b F l o a t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order % specified by the endian member of the image structure. % % The format of the WriteBlobFloat method is: % % ssize_t WriteBlobFloat(Image *image,const float value) % % A description of each parameter follows. % % o image: the image. % % o value: Specifies the value to write. % */ MagickExport ssize_t WriteBlobFloat(Image *image,const float value) { union { unsigned int unsigned_value; float float_value; } quantum; quantum.unsigned_value=0U; quantum.float_value=value; return(WriteBlobLong(image,quantum.unsigned_value)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order % specified by the endian member of the image structure. % % The format of the WriteBlobLong method is: % % ssize_t WriteBlobLong(Image *image,const unsigned int value) % % A description of each parameter follows. % % o image: the image. % % o value: Specifies the value to write. % */ MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value) { unsigned char buffer[4]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->endian == LSBEndian) { buffer[0]=(unsigned char) value; buffer[1]=(unsigned char) (value >> 8); buffer[2]=(unsigned char) (value >> 16); buffer[3]=(unsigned char) (value >> 24); return(WriteBlobStream(image,4,buffer)); } buffer[0]=(unsigned char) (value >> 24); buffer[1]=(unsigned char) (value >> 16); buffer[2]=(unsigned char) (value >> 8); buffer[3]=(unsigned char) value; return(WriteBlobStream(image,4,buffer)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b S h o r t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobShort() writes a short value as a 16-bit quantity in the % byte-order specified by the endian member of the image structure. % % The format of the WriteBlobShort method is: % % ssize_t WriteBlobShort(Image *image,const unsigned short value) % % A description of each parameter follows. % % o image: the image. % % o value: Specifies the value to write. % */ MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value) { unsigned char buffer[2]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->endian == LSBEndian) { buffer[0]=(unsigned char) value; buffer[1]=(unsigned char) (value >> 8); return(WriteBlobStream(image,2,buffer)); } buffer[0]=(unsigned char) (value >> 8); buffer[1]=(unsigned char) value; return(WriteBlobStream(image,2,buffer)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b L S B L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in % least-significant byte first order. % % The format of the WriteBlobLSBLong method is: % % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value) % % A description of each parameter follows. % % o image: the image. % % o value: Specifies the value to write. % */ MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value) { unsigned char buffer[4]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); buffer[0]=(unsigned char) value; buffer[1]=(unsigned char) (value >> 8); buffer[2]=(unsigned char) (value >> 16); buffer[3]=(unsigned char) (value >> 24); return(WriteBlobStream(image,4,buffer)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b L S B S h o r t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in % least-significant byte first order. % % The format of the WriteBlobLSBShort method is: % % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value) % % A description of each parameter follows. % % o image: the image. % % o value: Specifies the value to write. % */ MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value) { unsigned char buffer[2]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); buffer[0]=(unsigned char) value; buffer[1]=(unsigned char) (value >> 8); return(WriteBlobStream(image,2,buffer)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b M S B L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in % most-significant byte first order. % % The format of the WriteBlobMSBLong method is: % % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value) % % A description of each parameter follows. % % o value: Specifies the value to write. % % o image: the image. % */ MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value) { unsigned char buffer[4]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); buffer[0]=(unsigned char) (value >> 24); buffer[1]=(unsigned char) (value >> 16); buffer[2]=(unsigned char) (value >> 8); buffer[3]=(unsigned char) value; return(WriteBlobStream(image,4,buffer)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b M S B L o n g L o n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in % most-significant byte first order. % % The format of the WriteBlobMSBLongLong method is: % % ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value) % % A description of each parameter follows. % % o value: Specifies the value to write. % % o image: the image. % */ MagickExport ssize_t WriteBlobMSBLongLong(Image *image, const MagickSizeType value) { unsigned char buffer[8]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); buffer[0]=(unsigned char) (value >> 56); buffer[1]=(unsigned char) (value >> 48); buffer[2]=(unsigned char) (value >> 40); buffer[3]=(unsigned char) (value >> 32); buffer[4]=(unsigned char) (value >> 24); buffer[5]=(unsigned char) (value >> 16); buffer[6]=(unsigned char) (value >> 8); buffer[7]=(unsigned char) value; return(WriteBlobStream(image,8,buffer)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b M S B S h o r t % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in % most-significant byte first order. % % The format of the WriteBlobMSBShort method is: % % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value) % % A description of each parameter follows. % % o value: Specifies the value to write. % % o file: Specifies the file to write the data to. % */ MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value) { unsigned char buffer[2]; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); buffer[0]=(unsigned char) (value >> 8); buffer[1]=(unsigned char) value; return(WriteBlobStream(image,2,buffer)); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + W r i t e B l o b S t r i n g % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteBlobString() write a string to a blob. It returns the number of % characters written. % % The format of the WriteBlobString method is: % % ssize_t WriteBlobString(Image *image,const char *string) % % A description of each parameter follows. % % o image: the image. % % o string: Specifies the string to write. % */ MagickExport ssize_t WriteBlobString(Image *image,const char *string) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(string != (const char *) NULL); return(WriteBlobStream(image,strlen(string),(const unsigned char *) string)); }