Coverage Report

Created: 2026-03-31 06:56

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