This source file includes following definitions.
- AttachBlob
- BlobToFile
- BlobToImage
- CloneBlobInfo
- CloseBlob
- DestroyBlob
- DetachBlob
- DisassociateBlob
- DiscardBlobBytes
- DuplicateBlob
- EOFBlob
- FileToBlob
- WriteBlobStream
- FileToImage
- GetBlobError
- GetBlobFileHandle
- GetBlobInfo
- GetBlobProperties
- GetBlobSize
- GetBlobStreamData
- GetBlobStreamHandler
- ImageToBlob
- ImageToFile
- ImagesToBlob
- InjectImageBlob
- IsBlobExempt
- IsBlobSeekable
- IsBlobTemporary
- MapBlob
- MSBOrderLong
- MSBOrderShort
- SetStreamBuffering
- OpenBlob
- PingStream
- PingBlob
- ReadBlob
- ReadBlobByte
- ReadBlobDouble
- ReadBlobFloat
- ReadBlobLong
- ReadBlobLongLong
- ReadBlobShort
- ReadBlobLSBLong
- ReadBlobLSBShort
- ReadBlobMSBLong
- ReadBlobMSBLongLong
- ReadBlobMSBShort
- ReadBlobStream
- ReadBlobString
- ReferenceBlob
- SeekBlob
- SetBlobExempt
- SetBlobExtent
- SyncBlob
- TellBlob
- UnmapBlob
- WriteBlob
- WriteBlobByte
- WriteBlobFloat
- WriteBlobLong
- WriteBlobShort
- WriteBlobLSBLong
- WriteBlobLSBShort
- WriteBlobMSBLong
- WriteBlobMSBLongLong
- WriteBlobMSBShort
- WriteBlobString
#ifdef __VMS
#include <types.h>
#include <mman.h>
#endif
#include "magick/studio.h"
#include "magick/blob.h"
#include "magick/blob-private.h"
#include "magick/cache.h"
#include "magick/client.h"
#include "magick/constitute.h"
#include "magick/delegate.h"
#include "magick/exception.h"
#include "magick/exception-private.h"
#include "magick/image-private.h"
#include "magick/list.h"
#include "magick/locale_.h"
#include "magick/log.h"
#include "magick/magick.h"
#include "magick/memory_.h"
#include "magick/nt-base-private.h"
#include "magick/option.h"
#include "magick/policy.h"
#include "magick/resource_.h"
#include "magick/semaphore.h"
#include "magick/string_.h"
#include "magick/string-private.h"
#include "magick/token.h"
#include "magick/utility.h"
#include "magick/utility-private.h"
#if defined(MAGICKCORE_ZLIB_DELEGATE)
#include "zlib.h"
#endif
#if defined(MAGICKCORE_BZLIB_DELEGATE)
#include "bzlib.h"
#endif
#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(__OS2__)
#include <io.h>
#define _O_BINARY O_BINARY
#endif
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,
immutable,
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;
};
static int
SyncBlob(Image *);
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;
blob_info->immutable=MagickTrue;
}
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=write(file,(const char *) blob+i,MagickMin(length-i,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);
}
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)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
blob_info->magick);
blob_info=DestroyImageInfo(blob_info);
return((Image *) NULL);
}
if (GetMagickBlobSupport(magick_info) != MagickFalse)
{
(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);
}
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;
for (images=GetFirstImageInList(image); images != (Image *) NULL; )
{
(void) CopyMagickString(images->filename,image_info->filename,
MaxTextExtent);
(void) CopyMagickString(images->magick_filename,image_info->filename,
MaxTextExtent);
(void) CopyMagickString(images->magick,magick_info->name,MaxTextExtent);
images=GetNextImageInList(images);
}
}
clone_info=DestroyImageInfo(clone_info);
(void) RelinquishUniqueFileResource(blob_info->filename);
blob_info=DestroyImageInfo(blob_info);
return(image);
}
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->immutable=blob_info->immutable;
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);
}
MagickExport MagickBooleanType CloseBlob(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);
if (image->blob->type == UndefinedStream)
return(MagickTrue);
status=SyncBlob(image);
switch (image->blob->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
case PipeStream:
{
if (image->blob->synchronize != MagickFalse)
status=fsync(fileno(image->blob->file_info.file));
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:
break;
case BlobStream:
{
if ((image->blob->file_info.file != (FILE *) NULL) &&
(image->blob->synchronize != MagickFalse))
{
(void) fsync(fileno(image->blob->file_info.file));
status=ferror(image->blob->file_info.file);
}
break;
}
}
image->blob->status=status < 0 ? MagickTrue : MagickFalse;
image->blob->size=GetBlobSize(image);
image->extent=image->blob->size;
image->blob->eof=MagickFalse;
if (image->blob->exempt != MagickFalse)
{
image->blob->type=UndefinedStream;
return(image->blob->status);
}
switch (image->blob->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
{
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)
status=fclose(image->blob->file_info.file);
break;
}
}
(void) DetachBlob(image->blob);
image->blob->status=status < 0 ? MagickTrue : MagickFalse;
return(image->blob->status);
}
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);
RelinquishMagickResource(MapResource,image->blob->length);
}
if (image->blob->semaphore != (SemaphoreInfo *) NULL)
DestroySemaphoreInfo(&image->blob->semaphore);
image->blob->signature=(~MagickSignature);
image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
}
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->data=(unsigned char *) NULL;
RelinquishMagickResource(MapResource,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->immutable=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);
}
MagickPrivate void DisassociateBlob(Image *image)
{
BlobInfo
*blob;
MagickBooleanType
clone;
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);
clone=MagickFalse;
LockSemaphoreInfo(image->blob->semaphore);
assert(image->blob->reference_count >= 0);
if (image->blob->reference_count > 1)
clone=MagickTrue;
UnlockSemaphoreInfo(image->blob->semaphore);
if (clone == MagickFalse)
return;
blob=CloneBlobInfo(image->blob);
DestroyBlob(image);
image->blob=blob;
}
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);
if (length != (MagickSizeType) ((MagickOffsetType) length))
return(MagickFalse);
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);
}
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);
}
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);
}
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 ((file == fileno(stdin)) || (offset < 0) ||
(offset != (MagickOffsetType) ((ssize_t) offset)))
{
size_t
quantum;
struct stat
file_stats;
offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
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));
for (i=0; blob != (unsigned char *) NULL; i+=count)
{
count=read(file,blob+i,quantum);
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
if (~((size_t) 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(offset,(MagickOffsetType)
MagickMin(extent,SSIZE_MAX));
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=read(file,blob+i,MagickMin(*length-i,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);
}
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)
{
extent=image->blob->extent+image->blob->quantum+length;
image->blob->quantum<<=1;
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)
{
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=fileno(stdin);
if (LocaleCompare(filename,"-") != 0)
file=open_utf8(filename,O_RDONLY | O_BINARY,0);
if (file == -1)
{
ThrowFileException(&image->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)
{
file=close(file);
ThrowFileException(&image->exception,ResourceLimitError,
"MemoryAllocationFailed",filename);
return(MagickFalse);
}
for ( ; ; )
{
count=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(&image->exception,BlobError,"UnableToWriteBlob",
filename);
break;
}
}
file=close(file);
if (file == -1)
ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
filename);
blob=(unsigned char *) RelinquishMagickMemory(blob);
return(MagickTrue);
}
MagickExport 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);
}
MagickExport FILE *GetBlobFileHandle(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
return(image->blob->file_info.file);
}
MagickExport 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;
}
MagickExport 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);
}
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);
}
MagickExport unsigned char *GetBlobStreamData(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
return(image->blob->data);
}
MagickExport 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);
}
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->magick);
blob_info=DestroyImageInfo(blob_info);
return(blob);
}
(void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
if (GetMagickBlobSupport(magick_info) != MagickFalse)
{
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);
InheritException(exception,&image->exception);
*length=image->blob->length;
blob=DetachBlob(image->blob);
if (status == MagickFalse)
blob=(unsigned char *) RelinquishMagickMemory(blob);
else
blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
sizeof(*blob));
}
}
else
{
char
unique[MaxTextExtent];
int
file;
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);
(void) CloseBlob(image);
(void) fclose(blob_info->file);
if (status == MagickFalse)
InheritException(exception,&image->exception);
else
blob=FileToBlob(unique,~0UL,length,exception);
}
(void) RelinquishUniqueFileResource(unique);
}
}
blob_info=DestroyImageInfo(blob_info);
return(blob);
}
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(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=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
for (i=0; count > 0; )
{
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;
p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
}
if (LocaleCompare(filename,"-") != 0)
file=close(file);
buffer=(unsigned char *) RelinquishMagickMemory(buffer);
if ((file == -1) || (i < length))
{
if (file != -1)
file=close(file);
ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
return(MagickFalse);
}
return(MagickTrue);
}
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);
magick_info=GetMagickInfo(images->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
images->magick);
blob_info=DestroyImageInfo(blob_info);
return(blob);
}
if (GetMagickAdjoin(magick_info) == MagickFalse)
{
blob_info=DestroyImageInfo(blob_info);
return(ImageToBlob(image_info,images,length,exception));
}
(void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
if (GetMagickBlobSupport(magick_info) != MagickFalse)
{
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
{
(void) CloseBlob(images);
images->blob->exempt=MagickTrue;
*images->filename='\0';
status=WriteImages(blob_info,images,images->filename,exception);
*length=images->blob->length;
blob=DetachBlob(images->blob);
if (status == MagickFalse)
blob=(unsigned char *) RelinquishMagickMemory(blob);
else
blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
sizeof(*blob));
}
}
else
{
char
filename[MaxTextExtent],
unique[MaxTextExtent];
int
file;
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) CloseBlob(images);
(void) fclose(blob_info->file);
if (status == MagickFalse)
InheritException(exception,&images->exception);
else
blob=FileToBlob(unique,~0UL,length,exception);
}
(void) RelinquishUniqueFileResource(unique);
}
}
blob_info=DestroyImageInfo(blob_info);
return(blob);
}
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;
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);
*write_info->magick='\0';
SetImageInfoFile(write_info,unique_file);
status=WriteImage(write_info,byte_image);
write_info=DestroyImageInfo(write_info);
byte_image=DestroyImage(byte_image);
(void) fclose(unique_file);
if (status == MagickFalse)
{
(void) RelinquishUniqueFileResource(filename);
return(MagickFalse);
}
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);
file=close(file);
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
for (i=0; ; i+=count)
{
count=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);
}
MagickExport 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);
}
MagickExport 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);
}
MagickExport 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);
}
MagickExport unsigned char *MapBlob(int file,const MapMode mode,
const MagickOffsetType offset,const size_t length)
{
#if defined(MAGICKCORE_HAVE_MMAP)
int
flags,
protection;
unsigned char
*map;
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;
break;
}
case WriteMode:
{
protection=PROT_WRITE;
flags|=MAP_SHARED;
break;
}
case IOMode:
{
protection=PROT_READ | PROT_WRITE;
flags|=MAP_SHARED;
break;
}
}
#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
(off_t) offset);
#else
map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
MAP_HUGETLB,file,(off_t) offset);
if (map == (unsigned char *) MAP_FAILED)
map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
(off_t) offset);
#endif
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
}
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;
}
}
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;
}
}
static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
Image *image)
{
const char
*option;
int
status;
size_t
size;
size=16384;
option=GetImageOption(image_info,"stream:buffer-size");
if (option != (const char *) NULL)
size=StringToUnsignedLong(option);
status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
_IONBF : _IOFBF,size);
return(status == 0 ? MagickTrue : MagickFalse);
}
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);
}
}
*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(SetStreamBuffering(image_info,image));
}
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(SetStreamBuffering(image_info,image));
}
#if defined(MAGICKCORE_HAVE_POPEN)
if (*filename == '|')
{
char
mode[MaxTextExtent];
#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(SetStreamBuffering(image_info,image));
}
#endif
status=GetPathAttributes(filename,&image->blob->properties);
#if defined(S_ISFIFO)
if ((status != MagickFalse) && 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(SetStreamBuffering(image_info,image));
}
#endif
GetPathComponent(image->filename,ExtensionPath,extension);
if (*type == 'w')
{
(void) CopyMagickString(filename,image->filename,MaxTextExtent);
if ((image_info->adjoin == MagickFalse) ||
(strchr(filename,'%') != (char *) NULL))
{
(void) InterpretImageFilename(image_info,image,image->filename,(int)
image->scene,filename);
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;
(void) SetStreamBuffering(image_info,image);
(void) ResetMagickMemory(magick,0,sizeof(magick));
count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
(void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
#if defined(MAGICKCORE_POSIX_SUPPORT)
(void) fflush(image->blob->file_info.file);
#endif
(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))
{
if (image->blob->file_info.file != (FILE *) NULL)
(void) fclose(image->blob->file_info.file);
image->blob->file_info.file=(FILE *) NULL;
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)
{
if (image->blob->file_info.file != (FILE *) NULL)
(void) fclose(image->blob->file_info.file);
image->blob->file_info.file=(FILE *) NULL;
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;
size_t
length;
sans_exception=AcquireExceptionInfo();
magick_info=GetMagickInfo(image_info->magick,sans_exception);
sans_exception=DestroyExceptionInfo(sans_exception);
length=(size_t) image->blob->properties.st_size;
if ((magick_info != (const MagickInfo *) NULL) &&
(GetMagickBlobSupport(magick_info) != MagickFalse) &&
(length > MagickMaxBufferExtent) &&
(AcquireMagickResource(MapResource,length) != MagickFalse))
{
void
*blob;
blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
length);
if (blob == (void *) NULL)
RelinquishMagickResource(MapResource,length);
else
{
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;
(void) SetStreamBuffering(image_info,image);
}
}
image->blob->status=MagickFalse;
if (image->blob->type != UndefinedStream)
image->blob->size=GetBlobSize(image);
else
{
ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
return(MagickFalse);
}
return(MagickTrue);
}
#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)
{
magick_unreferenced(image);
magick_unreferenced(pixels);
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);
}
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:
case FileStream:
case PipeStream:
{
switch (length)
{
default:
{
count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
break;
}
case 4:
{
c=getc(image->blob->file_info.file);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 3:
{
c=getc(image->blob->file_info.file);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
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 4:
{
c=gzgetc(image->blob->file_info.gzfile);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 3:
{
c=gzgetc(image->blob->file_info.gzfile);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
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,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);
}
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=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
if (count != 1)
return(EOF);
return((int) (*p));
}
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);
}
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);
}
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=(const unsigned char *) 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);
}
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=(const unsigned char *) 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));
}
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=(const unsigned char *) 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));
}
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=(const unsigned char *) 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);
}
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=(const unsigned char *) 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));
}
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=(const unsigned char *) 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);
}
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=(const unsigned char *) 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));
}
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=(const unsigned char *) 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));
}
MagickExport const void *ReadBlobStream(Image *image,const size_t length,
void *data,ssize_t *count)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
assert(count != (ssize_t *) NULL);
if (image->blob->type != BlobStream)
{
assert(data != NULL);
*count=ReadBlob(image,length,(unsigned char *) 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,image->blob->length-image->blob->offset);
image->blob->offset+=(*count);
if (*count != (ssize_t) length)
image->blob->eof=MagickTrue;
return(data);
}
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=(const unsigned char *) 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);
}
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);
}
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 ((offset < 0) && (whence == SEEK_SET))
return(-1);
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;
break;
}
if (image->blob->offset < (MagickOffsetType)
((off_t) image->blob->extent))
break;
if (image->blob->immutable != MagickFalse)
{
image->blob->eof=MagickTrue;
return(-1);
}
image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
image->blob->quantum<<=1;
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);
}
MagickExport 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;
}
MagickExport 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:
{
MagickOffsetType
offset;
ssize_t
count;
if (extent != (MagickSizeType) ((off_t) extent))
return(MagickFalse);
offset=SeekBlob(image,0,SEEK_END);
if (offset < 0)
return(MagickFalse);
if ((MagickSizeType) offset >= extent)
break;
offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
if (offset < 0)
break;
count=(ssize_t) fwrite((const unsigned char *) "",1,1,
image->blob->file_info.file);
#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
if (image->blob->synchronize != MagickFalse)
(void) posix_fallocate(fileno(image->blob->file_info.file),offset,
extent-offset);
#endif
offset=SeekBlob(image,offset,SEEK_SET);
if (count != 1)
return(MagickFalse);
break;
}
case PipeStream:
case ZipStream:
return(MagickFalse);
case BZipStream:
return(MagickFalse);
case FifoStream:
return(MagickFalse);
case BlobStream:
{
if (extent != (MagickSizeType) ((size_t) extent))
return(MagickFalse);
if (image->blob->mapped != MagickFalse)
{
MagickOffsetType
offset;
ssize_t
count;
(void) UnmapBlob(image->blob->data,image->blob->length);
RelinquishMagickResource(MapResource,image->blob->length);
if (extent != (MagickSizeType) ((off_t) extent))
return(MagickFalse);
offset=SeekBlob(image,0,SEEK_END);
if (offset < 0)
return(MagickFalse);
if ((MagickSizeType) offset >= extent)
break;
offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
count=(ssize_t) fwrite((const unsigned char *) "",1,1,
image->blob->file_info.file);
#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
if (image->blob->synchronize != MagickFalse)
{
int
file;
file=fileno(image->blob->file_info.file);
if ((file == -1) || (offset < 0))
return(MagickFalse);
(void) posix_fallocate(file,offset,extent-offset);
}
#endif
offset=SeekBlob(image,offset,SEEK_SET);
if (count != 1)
return(MagickFalse);
(void) AcquireMagickResource(MapResource,extent);
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;
}
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);
}
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:
break;
}
return(status);
}
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);
}
MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
{
#if defined(MAGICKCORE_HAVE_MMAP)
int
status;
status=munmap(map,length);
return(status == -1 ? MagickFalse : MagickTrue);
#else
(void) map;
(void) length;
return(MagickFalse);
#endif
}
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:
case FileStream:
case PipeStream:
{
switch (length)
{
default:
{
count=(ssize_t) fwrite((const char *) data,1,length,
image->blob->file_info.file);
break;
}
case 4:
{
c=putc((int) *p++,image->blob->file_info.file);
if (c == EOF)
break;
count++;
}
case 3:
{
c=putc((int) *p++,image->blob->file_info.file);
if (c == EOF)
break;
count++;
}
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 4:
{
c=gzputc(image->blob->file_info.gzfile,(int) *p++);
if (c == EOF)
break;
count++;
}
case 3:
{
c=gzputc(image->blob->file_info.gzfile,(int) *p++);
if (c == EOF)
break;
count++;
}
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->extent+=length+image->blob->quantum;
image->blob->quantum<<=1;
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);
}
MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
return(WriteBlobStream(image,1,&value));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}
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));
}