Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
      7 %             U   U    T      I    L        I      T     Y Y                  %
      8 %             U   U    T      I    L        I      T      Y                   %
      9 %             U   U    T      I    L        I      T      Y                   %
     10 %              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
     11 %                                                                             %
     12 %                                                                             %
     13 %                       MagickCore Utility Methods                            %
     14 %                                                                             %
     15 %                             Software Design                                 %
     16 %                                  Cristy                                     %
     17 %                              January 1993                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 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 %    http://www.imagemagick.org/script/license.php                            %
     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 /*
     41   Include declarations.
     42 */
     43 #include "MagickCore/studio.h"
     44 #include "MagickCore/property.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/color.h"
     47 #include "MagickCore/exception.h"
     48 #include "MagickCore/exception-private.h"
     49 #include "MagickCore/geometry.h"
     50 #include "MagickCore/image-private.h"
     51 #include "MagickCore/list.h"
     52 #include "MagickCore/log.h"
     53 #include "MagickCore/magick-private.h"
     54 #include "MagickCore/memory_.h"
     55 #include "MagickCore/nt-base-private.h"
     56 #include "MagickCore/option.h"
     57 #include "MagickCore/policy.h"
     58 #include "MagickCore/random_.h"
     59 #include "MagickCore/registry.h"
     60 #include "MagickCore/resource_.h"
     61 #include "MagickCore/semaphore.h"
     62 #include "MagickCore/signature-private.h"
     63 #include "MagickCore/statistic.h"
     64 #include "MagickCore/string_.h"
     65 #include "MagickCore/string-private.h"
     66 #include "MagickCore/token.h"
     67 #include "MagickCore/token-private.h"
     68 #include "MagickCore/utility.h"
     69 #include "MagickCore/utility-private.h"
     70 #if defined(MAGICKCORE_HAVE_PROCESS_H)
     71 #include <process.h>
     72 #endif
     73 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
     74 #include <mach-o/dyld.h>
     75 #endif
     76 
     77 /*
     79   Static declarations.
     80 */
     81 static const char
     82   Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     83 
     84 /*
     86   Forward declaration.
     87 */
     88 static int
     89   IsPathDirectory(const char *);
     90 
     91 /*
     93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     94 %                                                                             %
     95 %                                                                             %
     96 %                                                                             %
     97 %   A c q u i r e U n i q u e F i l e n a m e                                 %
     98 %                                                                             %
     99 %                                                                             %
    100 %                                                                             %
    101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    102 %
    103 %  AcquireUniqueFilename() replaces the contents of path by a unique path name.
    104 %
    105 %  The format of the AcquireUniqueFilename method is:
    106 %
    107 %      MagickBooleanType AcquireUniqueFilename(char *path)
    108 %
    109 %  A description of each parameter follows.
    110 %
    111 %   o  path:  Specifies a pointer to an array of characters.  The unique path
    112 %      name is returned in this array.
    113 %
    114 */
    115 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
    116 {
    117   int
    118     file;
    119 
    120   file=AcquireUniqueFileResource(path);
    121   if (file == -1)
    122     return(MagickFalse);
    123   file=close(file)-1;
    124   return(MagickTrue);
    125 }
    126 
    127 /*
    129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    130 %                                                                             %
    131 %                                                                             %
    132 %                                                                             %
    133 %   A c q u i r e U n i q u e S ym b o l i c L i n k                          %
    134 %                                                                             %
    135 %                                                                             %
    136 %                                                                             %
    137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    138 %
    139 %  AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified
    140 %  source path and returns MagickTrue on success otherwise MagickFalse.  If the
    141 %  symlink() method fails or is not available, a unique file name is generated
    142 %  and the source file copied to it.  When you are finished with the file, use
    143 %  RelinquishUniqueFilename() to destroy it.
    144 %
    145 %  The format of the AcquireUniqueSymbolicLink method is:
    146 %
    147 %      MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
    148 %        char destination)
    149 %
    150 %  A description of each parameter follows.
    151 %
    152 %   o  source:  the source path.
    153 %
    154 %   o  destination:  the destination path.
    155 %
    156 */
    157 
    158 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
    159   char *destination)
    160 {
    161   int
    162     destination_file,
    163     source_file;
    164 
    165   size_t
    166     length,
    167     quantum;
    168 
    169   ssize_t
    170     count;
    171 
    172   struct stat
    173     attributes;
    174 
    175   unsigned char
    176     *buffer;
    177 
    178   assert(source != (const char *) NULL);
    179   assert(destination != (char *) NULL);
    180 #if defined(MAGICKCORE_HAVE_SYMLINK)
    181   (void) AcquireUniqueFilename(destination);
    182   (void) RelinquishUniqueFileResource(destination);
    183   if (*source == *DirectorySeparator)
    184     {
    185       if (symlink(source,destination) == 0)
    186         return(MagickTrue);
    187     }
    188   else
    189     {
    190       char
    191         path[MagickPathExtent];
    192 
    193       *path='\0';
    194       if (getcwd(path,MagickPathExtent) == (char *) NULL)
    195         return(MagickFalse);
    196       (void) ConcatenateMagickString(path,DirectorySeparator,MagickPathExtent);
    197       (void) ConcatenateMagickString(path,source,MagickPathExtent);
    198       if (symlink(path,destination) == 0)
    199         return(MagickTrue);
    200     }
    201 #endif
    202   destination_file=AcquireUniqueFileResource(destination);
    203   if (destination_file == -1)
    204     return(MagickFalse);
    205   source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
    206   if (source_file == -1)
    207     {
    208       (void) close(destination_file);
    209       (void) RelinquishUniqueFileResource(destination);
    210       return(MagickFalse);
    211     }
    212   quantum=(size_t) MagickMaxBufferExtent;
    213   if ((fstat(source_file,&attributes) == 0) && (attributes.st_size > 0))
    214     quantum=(size_t) MagickMin(attributes.st_size,MagickMaxBufferExtent);
    215   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
    216   if (buffer == (unsigned char *) NULL)
    217     {
    218       (void) close(source_file);
    219       (void) close(destination_file);
    220       (void) RelinquishUniqueFileResource(destination);
    221       return(MagickFalse);
    222     }
    223   for (length=0; ; )
    224   {
    225     count=(ssize_t) read(source_file,buffer,quantum);
    226     if (count <= 0)
    227       break;
    228     length=(size_t) count;
    229     count=(ssize_t) write(destination_file,buffer,length);
    230     if ((size_t) count != length)
    231       {
    232         (void) close(destination_file);
    233         (void) close(source_file);
    234         buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    235         (void) RelinquishUniqueFileResource(destination);
    236         return(MagickFalse);
    237       }
    238   }
    239   (void) close(destination_file);
    240   (void) close(source_file);
    241   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    242   return(MagickTrue);
    243 }
    244 
    245 /*
    247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    248 %                                                                             %
    249 %                                                                             %
    250 %                                                                             %
    251 %  A p p e n d I m a g e F o r m a t                                          %
    252 %                                                                             %
    253 %                                                                             %
    254 %                                                                             %
    255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    256 %
    257 %  AppendImageFormat() appends the image format type to the filename.  If an
    258 %  extension to the file already exists, it is first removed.
    259 %
    260 %  The format of the AppendImageFormat method is:
    261 %
    262 %      void AppendImageFormat(const char *format,char *filename)
    263 %
    264 %  A description of each parameter follows.
    265 %
    266 %   o  format:  Specifies a pointer to an array of characters.  This the
    267 %      format of the image.
    268 %
    269 %   o  filename:  Specifies a pointer to an array of characters.  The unique
    270 %      file name is returned in this array.
    271 %
    272 */
    273 MagickExport void AppendImageFormat(const char *format,char *filename)
    274 {
    275   char
    276     extension[MagickPathExtent],
    277     root[MagickPathExtent];
    278 
    279   assert(format != (char *) NULL);
    280   assert(filename != (char *) NULL);
    281   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
    282   if ((*format == '\0') || (*filename == '\0'))
    283     return;
    284   if (LocaleCompare(filename,"-") == 0)
    285     {
    286       char
    287         message[MagickPathExtent];
    288 
    289       (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",format,
    290         filename);
    291       (void) CopyMagickString(filename,message,MagickPathExtent);
    292       return;
    293     }
    294   GetPathComponent(filename,ExtensionPath,extension);
    295   if ((LocaleCompare(extension,"Z") == 0) ||
    296       (LocaleCompare(extension,"bz2") == 0) ||
    297       (LocaleCompare(extension,"gz") == 0) ||
    298       (LocaleCompare(extension,"wmz") == 0) ||
    299       (LocaleCompare(extension,"svgz") == 0))
    300     {
    301       GetPathComponent(filename,RootPath,root);
    302       (void) CopyMagickString(filename,root,MagickPathExtent);
    303       GetPathComponent(filename,RootPath,root);
    304       (void) FormatLocaleString(filename,MagickPathExtent,"%s.%s.%s",root,
    305         format,extension);
    306       return;
    307     }
    308   GetPathComponent(filename,RootPath,root);
    309   (void) FormatLocaleString(filename,MagickPathExtent,"%s.%s",root,format);
    310 }
    311 
    312 /*
    314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    315 %                                                                             %
    316 %                                                                             %
    317 %                                                                             %
    318 %   B a s e 6 4 D e c o d e                                                   %
    319 %                                                                             %
    320 %                                                                             %
    321 %                                                                             %
    322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    323 %
    324 %  Base64Decode() decodes Base64-encoded text and returns its binary
    325 %  equivalent.  NULL is returned if the text is not valid Base64 data, or a
    326 %  memory allocation failure occurs.
    327 %
    328 %  The format of the Base64Decode method is:
    329 %
    330 %      unsigned char *Base64Decode(const char *source,length_t *length)
    331 %
    332 %  A description of each parameter follows:
    333 %
    334 %    o source:  A pointer to a Base64-encoded string.
    335 %
    336 %    o length: the number of bytes decoded.
    337 %
    338 */
    339 MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
    340 {
    341   int
    342     state;
    343 
    344   register const char
    345     *p,
    346     *q;
    347 
    348   register size_t
    349     i;
    350 
    351   unsigned char
    352     *decode;
    353 
    354   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    355   assert(source != (char *) NULL);
    356   assert(length != (size_t *) NULL);
    357   *length=0;
    358   decode=(unsigned char *) AcquireQuantumMemory((strlen(source)+3)/4,
    359     3*sizeof(*decode));
    360   if (decode == (unsigned char *) NULL)
    361     return((unsigned char *) NULL);
    362   i=0;
    363   state=0;
    364   for (p=source; *p != '\0'; p++)
    365   {
    366     if (isspace((int) ((unsigned char) *p)) != 0)
    367       continue;
    368     if (*p == '=')
    369       break;
    370     q=strchr(Base64,*p);
    371     if (q == (char *) NULL)
    372       {
    373         decode=(unsigned char *) RelinquishMagickMemory(decode);
    374         return((unsigned char *) NULL);  /* non-Base64 character */
    375       }
    376     switch (state)
    377     {
    378       case 0:
    379       {
    380         decode[i]=(q-Base64) << 2;
    381         state++;
    382         break;
    383       }
    384       case 1:
    385       {
    386         decode[i++]|=(q-Base64) >> 4;
    387         decode[i]=((q-Base64) & 0x0f) << 4;
    388         state++;
    389         break;
    390       }
    391       case 2:
    392       {
    393         decode[i++]|=(q-Base64) >> 2;
    394         decode[i]=((q-Base64) & 0x03) << 6;
    395         state++;
    396         break;
    397       }
    398       case 3:
    399       {
    400         decode[i++]|=(q-Base64);
    401         state=0;
    402         break;
    403       }
    404     }
    405   }
    406   /*
    407     Verify Base-64 string has proper terminal characters.
    408   */
    409   if (*p != '=')
    410     {
    411       if (state != 0)
    412         {
    413           decode=(unsigned char *) RelinquishMagickMemory(decode);
    414           return((unsigned char *) NULL);
    415         }
    416     }
    417   else
    418     {
    419       p++;
    420       switch (state)
    421       {
    422         case 0:
    423         case 1:
    424         {
    425           /*
    426             Unrecognized '=' character.
    427           */
    428           decode=(unsigned char *) RelinquishMagickMemory(decode);
    429           return((unsigned char *) NULL);
    430         }
    431         case 2:
    432         {
    433           for ( ; *p != '\0'; p++)
    434             if (isspace((int) ((unsigned char) *p)) == 0)
    435               break;
    436           if (*p != '=')
    437             {
    438               decode=(unsigned char *) RelinquishMagickMemory(decode);
    439               return((unsigned char *) NULL);
    440             }
    441           p++;
    442         }
    443         case 3:
    444         {
    445           for ( ; *p != '\0'; p++)
    446             if (isspace((int) ((unsigned char) *p)) == 0)
    447               {
    448                 decode=(unsigned char *) RelinquishMagickMemory(decode);
    449                 return((unsigned char *) NULL);
    450               }
    451           if ((int) decode[i] != 0)
    452             {
    453               decode=(unsigned char *) RelinquishMagickMemory(decode);
    454               return((unsigned char *) NULL);
    455             }
    456           break;
    457         }
    458       }
    459     }
    460   *length=i;
    461   return(decode);
    462 }
    463 
    464 /*
    466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    467 %                                                                             %
    468 %                                                                             %
    469 %                                                                             %
    470 %   B a s e 6 4 E n c o d e                                                   %
    471 %                                                                             %
    472 %                                                                             %
    473 %                                                                             %
    474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    475 %
    476 %  Base64Encode() encodes arbitrary binary data to Base64 encoded format as
    477 %  described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and
    478 %  returns the result as a null-terminated ASCII string.  NULL is returned if
    479 %  a memory allocation failure occurs.
    480 %
    481 %  The format of the Base64Encode method is:
    482 %
    483 %      char *Base64Encode(const unsigned char *blob,const size_t blob_length,
    484 %        size_t *encode_length)
    485 %
    486 %  A description of each parameter follows:
    487 %
    488 %    o blob:  A pointer to binary data to encode.
    489 %
    490 %    o blob_length: the number of bytes to encode.
    491 %
    492 %    o encode_length:  The number of bytes encoded.
    493 %
    494 */
    495 MagickExport char *Base64Encode(const unsigned char *blob,
    496   const size_t blob_length,size_t *encode_length)
    497 {
    498   char
    499     *encode;
    500 
    501   register const unsigned char
    502     *p;
    503 
    504   register size_t
    505     i;
    506 
    507   size_t
    508     remainder;
    509 
    510   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    511   assert(blob != (const unsigned char *) NULL);
    512   assert(blob_length != 0);
    513   assert(encode_length != (size_t *) NULL);
    514   *encode_length=0;
    515   encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
    516   if (encode == (char *) NULL)
    517     return((char *) NULL);
    518   i=0;
    519   for (p=blob; p < (blob+blob_length-2); p+=3)
    520   {
    521     encode[i++]=Base64[(int) (*p >> 2)];
    522     encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
    523     encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
    524     encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
    525   }
    526   remainder=blob_length % 3;
    527   if (remainder != 0)
    528     {
    529       ssize_t
    530         j;
    531 
    532       unsigned char
    533         code[3];
    534 
    535       code[0]='\0';
    536       code[1]='\0';
    537       code[2]='\0';
    538       for (j=0; j < (ssize_t) remainder; j++)
    539         code[j]=(*p++);
    540       encode[i++]=Base64[(int) (code[0] >> 2)];
    541       encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
    542       if (remainder == 1)
    543         encode[i++]='=';
    544       else
    545         encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
    546       encode[i++]='=';
    547     }
    548   *encode_length=i;
    549   encode[i++]='\0';
    550   return(encode);
    551 }
    552 
    553 /*
    555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    556 %                                                                             %
    557 %                                                                             %
    558 %                                                                             %
    559 %   C h o p P a t h C o m p o n e n t s                                       %
    560 %                                                                             %
    561 %                                                                             %
    562 %                                                                             %
    563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    564 %
    565 %  ChopPathComponents() removes the number of specified file components from a
    566 %  path.
    567 %
    568 %  The format of the ChopPathComponents method is:
    569 %
    570 %      ChopPathComponents(char *path,size_t components)
    571 %
    572 %  A description of each parameter follows:
    573 %
    574 %    o path:  The path.
    575 %
    576 %    o components:  The number of components to chop.
    577 %
    578 */
    579 MagickPrivate void ChopPathComponents(char *path,const size_t components)
    580 {
    581   register ssize_t
    582     i;
    583 
    584   for (i=0; i < (ssize_t) components; i++)
    585     GetPathComponent(path,HeadPath,path);
    586 }
    587 
    588 /*
    590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    591 %                                                                             %
    592 %                                                                             %
    593 %                                                                             %
    594 %   E x p a n d F i l e n a m e                                               %
    595 %                                                                             %
    596 %                                                                             %
    597 %                                                                             %
    598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    599 %
    600 %  ExpandFilename() expands '~' in a path.
    601 %
    602 %  The format of the ExpandFilename function is:
    603 %
    604 %      ExpandFilename(char *path)
    605 %
    606 %  A description of each parameter follows:
    607 %
    608 %    o path: Specifies a pointer to a character array that contains the
    609 %      path.
    610 %
    611 */
    612 MagickPrivate void ExpandFilename(char *path)
    613 {
    614   char
    615     expand_path[MagickPathExtent];
    616 
    617   if (path == (char *) NULL)
    618     return;
    619   if (*path != '~')
    620     return;
    621   (void) CopyMagickString(expand_path,path,MagickPathExtent);
    622   if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
    623     {
    624       char
    625         *home;
    626 
    627       /*
    628         Substitute ~ with $HOME.
    629       */
    630       (void) CopyMagickString(expand_path,".",MagickPathExtent);
    631       (void) ConcatenateMagickString(expand_path,path+1,MagickPathExtent);
    632       home=GetEnvironmentValue("HOME");
    633       if (home == (char *) NULL)
    634         home=GetEnvironmentValue("USERPROFILE");
    635       if (home != (char *) NULL)
    636         {
    637           (void) CopyMagickString(expand_path,home,MagickPathExtent);
    638           (void) ConcatenateMagickString(expand_path,path+1,MagickPathExtent);
    639           home=DestroyString(home);
    640         }
    641     }
    642   else
    643     {
    644 #if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
    645       char
    646         username[MagickPathExtent];
    647 
    648       register char
    649         *p;
    650 
    651       struct passwd
    652         *entry;
    653 
    654       /*
    655         Substitute ~ with home directory from password file.
    656       */
    657       (void) CopyMagickString(username,path+1,MagickPathExtent);
    658       p=strchr(username,'/');
    659       if (p != (char *) NULL)
    660         *p='\0';
    661       entry=getpwnam(username);
    662       if (entry == (struct passwd *) NULL)
    663         return;
    664       (void) CopyMagickString(expand_path,entry->pw_dir,MagickPathExtent);
    665       if (p != (char *) NULL)
    666         {
    667           (void) ConcatenateMagickString(expand_path,"/",MagickPathExtent);
    668           (void) ConcatenateMagickString(expand_path,p+1,MagickPathExtent);
    669         }
    670 #endif
    671     }
    672   (void) CopyMagickString(path,expand_path,MagickPathExtent);
    673 }
    674 
    675 /*
    677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    678 %                                                                             %
    679 %                                                                             %
    680 %                                                                             %
    681 %   E x p a n d F i l e n a m e s                                             %
    682 %                                                                             %
    683 %                                                                             %
    684 %                                                                             %
    685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    686 %
    687 %  ExpandFilenames() checks each argument of the given argument array, and
    688 %  expands it if they have a wildcard character.
    689 %
    690 %  Any coder prefix (EG: 'coder:filename') or read modifier postfix (EG:
    691 %  'filename[...]') are ignored during the file the expansion, but will be
    692 %  included in the final argument.  If no filename matching the meta-character
    693 %  'glob' is found the original argument is returned.
    694 %
    695 %  For example, an argument of '*.gif[20x20]' will be replaced by the list
    696 %    'abc.gif[20x20]',  'foobar.gif[20x20]',  'xyzzy.gif[20x20]'
    697 %  if such filenames exist, (in the current directory in this case).
    698 %
    699 %  Meta-characters handled...
    700 %     @    read a list of filenames (no further expansion performed)
    701 %     ~    At start of filename expands to HOME environemtn variable
    702 %     *    matches any string including an empty string
    703 %     ?    matches by any single character
    704 %
    705 %  WARNING: filenames starting with '.' (hidden files in a UNIX file system)
    706 %  will never be expanded.  Attempting to epand '.*' will produce no change.
    707 %
    708 %  Expansion is ignored for coders "label:" "caption:" "pango:" and "vid:".
    709 %  Which provide their own '@' meta-character handling.
    710 %
    711 %  You can see the results of the expansion using "Configure" log events.
    712 %
    713 %  The returned list should be freed using  DestroyStringList().
    714 %
    715 %  However the strings in the original pointed to argv are not
    716 %  freed  (TO BE CHECKED).  So a copy of the original pointer (and count)
    717 %  should be kept separate if they need to be freed later.
    718 %
    719 %  The format of the ExpandFilenames function is:
    720 %
    721 %      status=ExpandFilenames(int *number_arguments,char ***arguments)
    722 %
    723 %  A description of each parameter follows:
    724 %
    725 %    o number_arguments: Specifies a pointer to an integer describing the
    726 %      number of elements in the argument vector.
    727 %
    728 %    o arguments: Specifies a pointer to a text array containing the command
    729 %      line arguments.
    730 %
    731 */
    732 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
    733   char ***arguments)
    734 {
    735   char
    736     home_directory[MagickPathExtent],
    737     **vector;
    738 
    739   register ssize_t
    740     i,
    741     j;
    742 
    743   size_t
    744     number_files;
    745 
    746   ssize_t
    747     count,
    748     parameters;
    749 
    750   /*
    751     Allocate argument vector.
    752   */
    753   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    754   assert(number_arguments != (int *) NULL);
    755   assert(arguments != (char ***) NULL);
    756   vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
    757     sizeof(*vector));
    758   if (vector == (char **) NULL)
    759     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    760   /*
    761     Expand any wildcard filenames.
    762   */
    763   *home_directory='\0';
    764   count=0;
    765   for (i=0; i < (ssize_t) *number_arguments; i++)
    766   {
    767     char
    768       **filelist,
    769       filename[MagickPathExtent],
    770       magick[MagickPathExtent],
    771       *option,
    772       path[MagickPathExtent],
    773       subimage[MagickPathExtent];
    774 
    775     MagickBooleanType
    776       destroy;
    777 
    778     option=(*arguments)[i];
    779     *magick='\0';
    780     *path='\0';
    781     *filename='\0';
    782     *subimage='\0';
    783     number_files=0;
    784     vector[count++]=ConstantString(option);
    785     destroy=MagickTrue;
    786     parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
    787     if (parameters > 0)
    788       {
    789         /*
    790           Do not expand command option parameters.
    791         */
    792         for (j=0; j < parameters; j++)
    793         {
    794           i++;
    795           if (i == (ssize_t) *number_arguments)
    796             break;
    797           option=(*arguments)[i];
    798           vector[count++]=ConstantString(option);
    799         }
    800         continue;
    801       }
    802     if ((*option == '"') || (*option == '\''))
    803       continue;
    804     GetPathComponent(option,TailPath,filename);
    805     GetPathComponent(option,MagickPath,magick);
    806     if ((LocaleCompare(magick,"CAPTION") == 0) ||
    807         (LocaleCompare(magick,"LABEL") == 0) ||
    808         (LocaleCompare(magick,"PANGO") == 0) ||
    809         (LocaleCompare(magick,"VID") == 0))
    810       continue;
    811     if ((IsGlob(filename) == MagickFalse) && (*option != '@'))
    812       continue;
    813     if (*option != '@')
    814       {
    815         /*
    816           Generate file list from wildcard filename (e.g. *.jpg).
    817         */
    818         GetPathComponent(option,HeadPath,path);
    819         GetPathComponent(option,SubimagePath,subimage);
    820         ExpandFilename(path);
    821         if (*home_directory == '\0')
    822           getcwd_utf8(home_directory,MagickPathExtent-1);
    823         filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
    824           &number_files);
    825       }
    826     else
    827       {
    828         char
    829           *files;
    830 
    831         ExceptionInfo
    832           *exception;
    833 
    834         int
    835           length;
    836 
    837         /*
    838           Generate file list from file list (e.g. @filelist.txt).
    839         */
    840         exception=AcquireExceptionInfo();
    841         files=FileToString(option+1,~0UL,exception);
    842         exception=DestroyExceptionInfo(exception);
    843         if (files == (char *) NULL)
    844           continue;
    845         filelist=StringToArgv(files,&length);
    846         if (filelist == (char **) NULL)
    847           continue;
    848         files=DestroyString(files);
    849         filelist[0]=DestroyString(filelist[0]);
    850         for (j=0; j < (ssize_t) (length-1); j++)
    851           filelist[j]=filelist[j+1];
    852         number_files=(size_t) length-1;
    853       }
    854     if (filelist == (char **) NULL)
    855       continue;
    856     for (j=0; j < (ssize_t) number_files; j++)
    857       if (IsPathDirectory(filelist[j]) <= 0)
    858         break;
    859     if (j == (ssize_t) number_files)
    860       {
    861         for (j=0; j < (ssize_t) number_files; j++)
    862           filelist[j]=DestroyString(filelist[j]);
    863         filelist=(char **) RelinquishMagickMemory(filelist);
    864         continue;
    865       }
    866     /*
    867       Transfer file list to argument vector.
    868     */
    869     vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
    870       count+number_files+1,sizeof(*vector));
    871     if (vector == (char **) NULL)
    872       {
    873         for (j=0; j < (ssize_t) number_files; j++)
    874           filelist[j]=DestroyString(filelist[j]);
    875         filelist=(char **) RelinquishMagickMemory(filelist);
    876         return(MagickFalse);
    877       }
    878     for (j=0; j < (ssize_t) number_files; j++)
    879     {
    880       option=filelist[j];
    881       parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
    882       if (parameters > 0)
    883         {
    884           ssize_t
    885             k;
    886 
    887           /*
    888             Do not expand command option parameters.
    889           */
    890           vector[count++]=ConstantString(option);
    891           for (k=0; k < parameters; k++)
    892           {
    893             j++;
    894             if (j == (ssize_t) number_files)
    895               break;
    896             option=filelist[j];
    897             vector[count++]=ConstantString(option);
    898           }
    899           continue;
    900         }
    901       (void) CopyMagickString(filename,path,MagickPathExtent);
    902       if (*path != '\0')
    903         (void) ConcatenateMagickString(filename,DirectorySeparator,
    904           MagickPathExtent);
    905       if (filelist[j] != (char *) NULL)
    906         (void) ConcatenateMagickString(filename,filelist[j],MagickPathExtent);
    907       filelist[j]=DestroyString(filelist[j]);
    908       if (strlen(filename) >= (MagickPathExtent-1))
    909         ThrowFatalException(OptionFatalError,"FilenameTruncated");
    910       if (IsPathDirectory(filename) <= 0)
    911         {
    912           char
    913             path[MagickPathExtent];
    914 
    915           *path='\0';
    916           if (*magick != '\0')
    917             {
    918               (void) ConcatenateMagickString(path,magick,MagickPathExtent);
    919               (void) ConcatenateMagickString(path,":",MagickPathExtent);
    920             }
    921           (void) ConcatenateMagickString(path,filename,MagickPathExtent);
    922           if (*subimage != '\0')
    923             {
    924               (void) ConcatenateMagickString(path,"[",MagickPathExtent);
    925               (void) ConcatenateMagickString(path,subimage,MagickPathExtent);
    926               (void) ConcatenateMagickString(path,"]",MagickPathExtent);
    927             }
    928           if (strlen(path) >= (MagickPathExtent-1))
    929             ThrowFatalException(OptionFatalError,"FilenameTruncated");
    930           if (destroy != MagickFalse)
    931             {
    932               count--;
    933               vector[count]=DestroyString(vector[count]);
    934               destroy=MagickFalse;
    935             }
    936           vector[count++]=ConstantString(path);
    937         }
    938     }
    939     filelist=(char **) RelinquishMagickMemory(filelist);
    940   }
    941   vector[count]=(char *) NULL;
    942   if (IsEventLogging() != MagickFalse)
    943     {
    944       char
    945         *command_line;
    946 
    947       command_line=AcquireString(vector[0]);
    948       for (i=1; i < count; i++)
    949       {
    950         (void) ConcatenateString(&command_line," {");
    951         (void) ConcatenateString(&command_line,vector[i]);
    952         (void) ConcatenateString(&command_line,"}");
    953       }
    954       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
    955         "Command line: %s",command_line);
    956       command_line=DestroyString(command_line);
    957     }
    958   *number_arguments=(int) count;
    959   *arguments=vector;
    960   return(MagickTrue);
    961 }
    962 
    963 /*
    965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    966 %                                                                             %
    967 %                                                                             %
    968 %                                                                             %
    969 %   G e t E x e c u t i o n P a t h                                           %
    970 %                                                                             %
    971 %                                                                             %
    972 %                                                                             %
    973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    974 %
    975 %  GetExecutionPath() returns the pathname of the executable that started
    976 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
    977 %
    978 %  The format of the GetExecutionPath method is:
    979 %
    980 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
    981 %
    982 %  A description of each parameter follows:
    983 %
    984 %    o path: the pathname of the executable that started the process.
    985 %
    986 %    o extent: the maximum extent of the path.
    987 %
    988 */
    989 MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
    990 {
    991   char
    992     *directory;
    993 
    994   *path='\0';
    995   directory=getcwd(path,(unsigned long) extent);
    996   (void) directory;
    997 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
    998   {
    999     char
   1000       execution_path[PATH_MAX+1],
   1001       link_path[MagickPathExtent];
   1002 
   1003     ssize_t
   1004       count;
   1005 
   1006     (void) FormatLocaleString(link_path,MagickPathExtent,"/proc/%.20g/exe",
   1007       (double) getpid());
   1008     count=readlink(link_path,execution_path,PATH_MAX);
   1009     if (count == -1)
   1010       {
   1011         (void) FormatLocaleString(link_path,MagickPathExtent,"/proc/%.20g/file",
   1012           (double) getpid());
   1013         count=readlink(link_path,execution_path,PATH_MAX);
   1014       }
   1015     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
   1016       {
   1017         execution_path[count]='\0';
   1018         (void) CopyMagickString(path,execution_path,extent);
   1019       }
   1020   }
   1021 #endif
   1022 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
   1023   {
   1024     char
   1025       executable_path[PATH_MAX << 1],
   1026       execution_path[PATH_MAX+1];
   1027 
   1028     uint32_t
   1029       length;
   1030 
   1031     length=sizeof(executable_path);
   1032     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
   1033         (realpath(executable_path,execution_path) != (char *) NULL))
   1034       (void) CopyMagickString(path,execution_path,extent);
   1035   }
   1036 #endif
   1037 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
   1038   {
   1039     const char
   1040       *execution_path;
   1041 
   1042     execution_path=(const char *) getexecname();
   1043     if (execution_path != (const char *) NULL)
   1044       {
   1045         if (*execution_path != *DirectorySeparator)
   1046           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
   1047         (void) ConcatenateMagickString(path,execution_path,extent);
   1048       }
   1049   }
   1050 #endif
   1051 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
   1052   NTGetExecutionPath(path,extent);
   1053 #endif
   1054 #if defined(__GNU__)
   1055   {
   1056     char
   1057       *program_name,
   1058       *execution_path;
   1059 
   1060     ssize_t
   1061       count;
   1062 
   1063     count=0;
   1064     execution_path=(char *) NULL;
   1065     program_name=program_invocation_name;
   1066     if (*program_invocation_name != '/')
   1067       {
   1068         size_t
   1069           extent;
   1070 
   1071         extent=strlen(directory)+strlen(program_name)+2;
   1072         program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
   1073         if (program_name == (char *) NULL)
   1074           program_name=program_invocation_name;
   1075         else
   1076           count=FormatLocaleString(program_name,extent,"%s/%s",directory,
   1077             program_invocation_name);
   1078       }
   1079     if (count != -1)
   1080       {
   1081         execution_path=realpath(program_name,NULL);
   1082         if (execution_path != (char *) NULL)
   1083           (void) CopyMagickString(path,execution_path,extent);
   1084       }
   1085     if (program_name != program_invocation_name)
   1086       program_name=(char *) RelinquishMagickMemory(program_name);
   1087     execution_path=(char *) RelinquishMagickMemory(execution_path);
   1088   }
   1089 #endif
   1090 #if defined(__OpenBSD__)
   1091   {
   1092     extern char
   1093       *__progname;
   1094 
   1095     (void) CopyMagickString(path,__progname,extent);
   1096   }
   1097 #endif
   1098   return(IsPathAccessible(path));
   1099 }
   1100 
   1101 /*
   1103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1104 %                                                                             %
   1105 %                                                                             %
   1106 %                                                                             %
   1107 %   G e t M a g i c k P a g e S i z e                                         %
   1108 %                                                                             %
   1109 %                                                                             %
   1110 %                                                                             %
   1111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1112 %
   1113 %  GetMagickPageSize() returns the memory page size.
   1114 %
   1115 %  The format of the GetMagickPageSize method is:
   1116 %
   1117 %      ssize_t GetMagickPageSize()
   1118 %
   1119 */
   1120 MagickPrivate ssize_t GetMagickPageSize(void)
   1121 {
   1122   static ssize_t
   1123     page_size = -1;
   1124 
   1125   if (page_size > 0)
   1126     return(page_size);
   1127 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
   1128   page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
   1129 #else
   1130 #if defined(MAGICKCORE_HAVE_GETPAGESIZE)
   1131   page_size=(ssize_t) getpagesize();
   1132 #endif
   1133 #endif
   1134   if (page_size <= 0)
   1135     page_size=16384;
   1136   return(page_size);
   1137 }
   1138 
   1139 /*
   1141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1142 %                                                                             %
   1143 %                                                                             %
   1144 %                                                                             %
   1145 %   G e t P a t h A t t r i b u t e s                                         %
   1146 %                                                                             %
   1147 %                                                                             %
   1148 %                                                                             %
   1149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1150 %
   1151 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
   1152 %
   1153 %  The path of the GetPathAttributes method is:
   1154 %
   1155 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
   1156 %
   1157 %  A description of each parameter follows.
   1158 %
   1159 %   o  path: the file path.
   1160 %
   1161 %   o  attributes: the path attributes are returned here.
   1162 %
   1163 */
   1164 MagickExport MagickBooleanType GetPathAttributes(const char *path,
   1165   void *attributes)
   1166 {
   1167   MagickBooleanType
   1168     status;
   1169 
   1170   if (path == (const char *) NULL)
   1171     {
   1172       errno=EINVAL;
   1173       return(MagickFalse);
   1174     }
   1175   (void) ResetMagickMemory(attributes,0,sizeof(struct stat));
   1176   status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
   1177     MagickFalse;
   1178   return(status);
   1179 }
   1180 
   1181 /*
   1183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1184 %                                                                             %
   1185 %                                                                             %
   1186 %                                                                             %
   1187 %   G e t P a t h C o m p o n e n t                                           %
   1188 %                                                                             %
   1189 %                                                                             %
   1190 %                                                                             %
   1191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1192 %
   1193 %  GetPathComponent() returns the parent directory name, filename, basename, or
   1194 %  extension of a file path.
   1195 %
   1196 %  The component string pointed to must have at least MagickPathExtent space
   1197 %  for the results to be stored.
   1198 %
   1199 %  The format of the GetPathComponent function is:
   1200 %
   1201 %      GetPathComponent(const char *path,PathType type,char *component)
   1202 %
   1203 %  A description of each parameter follows:
   1204 %
   1205 %    o path: Specifies a pointer to a character array that contains the
   1206 %      file path.
   1207 %
   1208 %    o type: Specififies which file path component to return.
   1209 %
   1210 %    o component: the selected file path component is returned here.
   1211 %
   1212 */
   1213 MagickExport void GetPathComponent(const char *path,PathType type,
   1214   char *component)
   1215 {
   1216   char
   1217     *q;
   1218 
   1219   register char
   1220     *p;
   1221 
   1222   size_t
   1223     magick_length,
   1224     subimage_offset,
   1225     subimage_length;
   1226 
   1227   assert(path != (const char *) NULL);
   1228   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
   1229   assert(component != (char *) NULL);
   1230   if (*path == '\0')
   1231     {
   1232       *component='\0';
   1233       return;
   1234     }
   1235   (void) CopyMagickString(component,path,MagickPathExtent);
   1236   magick_length=0;
   1237 #if defined(__OS2__)
   1238   if (path[1] != ":")
   1239 #endif
   1240   for (p=component; *p != '\0'; p++)
   1241   {
   1242     if ((*p == '%') && (*(p+1) == '['))
   1243       {
   1244         /*
   1245           Skip over %[...].
   1246         */
   1247         for (p++; (*p != ']') && (*p != '\0'); p++) ;
   1248         if (*p == '\0')
   1249           break;
   1250       }
   1251     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
   1252         (IsPathAccessible(path) == MagickFalse))
   1253       {
   1254         /*
   1255           Look for image format specification (e.g. ps3:image).
   1256         */
   1257         *p='\0';
   1258         if (IsMagickConflict(component) != MagickFalse)
   1259           *p=':';
   1260         else
   1261           {
   1262             magick_length=(size_t) (p-component+1);
   1263             for (q=component; *(++p) != '\0'; q++)
   1264               *q=(*p);
   1265             *q='\0';
   1266           }
   1267         break;
   1268       }
   1269   }
   1270   subimage_length=0;
   1271   subimage_offset=0;
   1272   p=component;
   1273   if (*p != '\0')
   1274     p=component+strlen(component)-1;
   1275   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
   1276       (IsPathAccessible(path) == MagickFalse))
   1277     {
   1278       /*
   1279         Look for scene specification (e.g. img0001.pcd[4]).
   1280       */
   1281       for (q=p-1; q > component; q--)
   1282         if (*q == '[')
   1283           break;
   1284       if (*q == '[')
   1285         {
   1286           *p='\0';
   1287           if ((IsSceneGeometry(q+1,MagickFalse) == MagickFalse) &&
   1288               (IsGeometry(q+1) == MagickFalse))
   1289             *p=']';
   1290           else
   1291             {
   1292               subimage_length=(size_t) (p-q);
   1293               subimage_offset=magick_length+1+(size_t) (q-component);
   1294               *q='\0';
   1295             }
   1296         }
   1297     }
   1298   p=component;
   1299   if (*p != '\0')
   1300     for (p=component+strlen(component)-1; p > component; p--)
   1301       if (IsBasenameSeparator(*p) != MagickFalse)
   1302         break;
   1303   switch (type)
   1304   {
   1305     case MagickPath:
   1306     {
   1307       if (magick_length != 0)
   1308         (void) CopyMagickString(component,path,magick_length);
   1309       else
   1310         *component='\0';
   1311       break;
   1312     }
   1313     case RootPath:
   1314     {
   1315       for (p=component+(strlen(component)-1); p > component; p--)
   1316       {
   1317         if (IsBasenameSeparator(*p) != MagickFalse)
   1318           break;
   1319         if (*p == '.')
   1320           break;
   1321       }
   1322       if (*p == '.')
   1323         *p='\0';
   1324       break;
   1325     }
   1326     case HeadPath:
   1327     {
   1328       *p='\0';
   1329       break;
   1330     }
   1331     case TailPath:
   1332     {
   1333       if (IsBasenameSeparator(*p) != MagickFalse)
   1334         (void) CopyMagickMemory((unsigned char *) component,
   1335           (const unsigned char *) (p+1),strlen(p+1)+1);
   1336       break;
   1337     }
   1338     case BasePath:
   1339     {
   1340       if (IsBasenameSeparator(*p) != MagickFalse)
   1341         (void) CopyMagickString(component,p+1,MagickPathExtent);
   1342       for (p=component+(strlen(component)-1); p > component; p--)
   1343         if (*p == '.')
   1344           {
   1345             *p='\0';
   1346             break;
   1347           }
   1348       break;
   1349     }
   1350     case ExtensionPath:
   1351     {
   1352       if (IsBasenameSeparator(*p) != MagickFalse)
   1353         (void) CopyMagickString(component,p+1,MagickPathExtent);
   1354       p=component;
   1355       if (*p != '\0')
   1356         for (p=component+strlen(component)-1; p > component; p--)
   1357           if (*p == '.')
   1358             break;
   1359       *component='\0';
   1360       if (*p == '.')
   1361         (void) CopyMagickString(component,p+1,MagickPathExtent);
   1362       break;
   1363     }
   1364     case SubimagePath:
   1365     {
   1366       if (subimage_length != 0)
   1367         (void) CopyMagickString(component,path+subimage_offset,subimage_length);
   1368       else
   1369         *component = '\0';
   1370       break;
   1371     }
   1372     case CanonicalPath:
   1373     case UndefinedPath:
   1374       break;
   1375   }
   1376 }
   1377 
   1378 /*
   1380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1381 %                                                                             %
   1382 %                                                                             %
   1383 %                                                                             %
   1384 %  G e t P a t h C o m p o n e n t s                                          %
   1385 %                                                                             %
   1386 %                                                                             %
   1387 %                                                                             %
   1388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1389 %
   1390 %  GetPathComponents() returns a list of path components.
   1391 %
   1392 %  The format of the GetPathComponents method is:
   1393 %
   1394 %      char **GetPathComponents(const char *path,
   1395 %        size_t *number_componenets)
   1396 %
   1397 %  A description of each parameter follows:
   1398 %
   1399 %    o path:  Specifies the string to segment into a list.
   1400 %
   1401 %    o number_components:  return the number of components in the list
   1402 %
   1403 */
   1404 MagickPrivate char **GetPathComponents(const char *path,
   1405   size_t *number_components)
   1406 {
   1407   char
   1408     **components;
   1409 
   1410   register const char
   1411     *p,
   1412     *q;
   1413 
   1414   register ssize_t
   1415     i;
   1416 
   1417   if (path == (char *) NULL)
   1418     return((char **) NULL);
   1419   *number_components=1;
   1420   for (p=path; *p != '\0'; p++)
   1421     if (IsBasenameSeparator(*p))
   1422       (*number_components)++;
   1423   components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
   1424     sizeof(*components));
   1425   if (components == (char **) NULL)
   1426     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   1427   p=path;
   1428   for (i=0; i < (ssize_t) *number_components; i++)
   1429   {
   1430     for (q=p; *q != '\0'; q++)
   1431       if (IsBasenameSeparator(*q))
   1432         break;
   1433     components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MagickPathExtent,
   1434       sizeof(**components));
   1435     if (components[i] == (char *) NULL)
   1436       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   1437     (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
   1438     p=q+1;
   1439   }
   1440   components[i]=(char *) NULL;
   1441   return(components);
   1442 }
   1443 
   1444 /*
   1446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1447 %                                                                             %
   1448 %                                                                             %
   1449 %                                                                             %
   1450 %  I s P a t h A c c e s s i b l e                                            %
   1451 %                                                                             %
   1452 %                                                                             %
   1453 %                                                                             %
   1454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1455 %
   1456 %  IsPathAccessible() returns MagickTrue if the file as defined by the path is
   1457 %  accessible.
   1458 %
   1459 %  The format of the IsPathAccessible method is:
   1460 %
   1461 %      MagickBooleanType IsPathAccessible(const char *path)
   1462 %
   1463 %  A description of each parameter follows.
   1464 %
   1465 %    o path:  Specifies a path to a file.
   1466 %
   1467 */
   1468 MagickExport MagickBooleanType IsPathAccessible(const char *path)
   1469 {
   1470   MagickBooleanType
   1471     status;
   1472 
   1473   struct stat
   1474     attributes;
   1475 
   1476   if ((path == (const char *) NULL) || (*path == '\0'))
   1477     return(MagickFalse);
   1478   if (LocaleCompare(path,"-") == 0)
   1479     return(MagickTrue);
   1480   status=GetPathAttributes(path,&attributes);
   1481   if (status == MagickFalse)
   1482     return(status);
   1483   if (S_ISREG(attributes.st_mode) == 0)
   1484     return(MagickFalse);
   1485   if (access_utf8(path,F_OK) != 0)
   1486     return(MagickFalse);
   1487   return(MagickTrue);
   1488 }
   1489 
   1490 /*
   1492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1493 %                                                                             %
   1494 %                                                                             %
   1495 %                                                                             %
   1496 +  I s P a t h D i r e c t o r y                                              %
   1497 %                                                                             %
   1498 %                                                                             %
   1499 %                                                                             %
   1500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1501 %
   1502 %  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
   1503 %  if the path represents a directory otherwise 0.
   1504 %
   1505 %  The format of the IsPathDirectory method is:
   1506 %
   1507 %      int IsPathDirectory(const char *path)
   1508 %
   1509 %  A description of each parameter follows.
   1510 %
   1511 %   o  path:  The directory path.
   1512 %
   1513 */
   1514 static int IsPathDirectory(const char *path)
   1515 {
   1516   MagickBooleanType
   1517     status;
   1518 
   1519   struct stat
   1520     attributes;
   1521 
   1522   if ((path == (const char *) NULL) || (*path == '\0'))
   1523     return(MagickFalse);
   1524   status=GetPathAttributes(path,&attributes);
   1525   if (status == MagickFalse)
   1526     return(-1);
   1527   if (S_ISDIR(attributes.st_mode) == 0)
   1528     return(0);
   1529   return(1);
   1530 }
   1531 
   1532 /*
   1534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1535 %                                                                             %
   1536 %                                                                             %
   1537 %                                                                             %
   1538 %   L i s t F i l e s                                                         %
   1539 %                                                                             %
   1540 %                                                                             %
   1541 %                                                                             %
   1542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1543 %
   1544 %  ListFiles() reads the directory specified and returns a list of filenames
   1545 %  contained in the directory sorted in ascending alphabetic order.
   1546 %
   1547 %  The format of the ListFiles function is:
   1548 %
   1549 %      char **ListFiles(const char *directory,const char *pattern,
   1550 %        ssize_t *number_entries)
   1551 %
   1552 %  A description of each parameter follows:
   1553 %
   1554 %    o filelist: Method ListFiles returns a list of filenames contained
   1555 %      in the directory.  If the directory specified cannot be read or it is
   1556 %      a file a NULL list is returned.
   1557 %
   1558 %    o directory: Specifies a pointer to a text string containing a directory
   1559 %      name.
   1560 %
   1561 %    o pattern: Specifies a pointer to a text string containing a pattern.
   1562 %
   1563 %    o number_entries:  This integer returns the number of filenames in the
   1564 %      list.
   1565 %
   1566 */
   1567 
   1568 #if defined(__cplusplus) || defined(c_plusplus)
   1569 extern "C" {
   1570 #endif
   1571 
   1572 static int FileCompare(const void *x,const void *y)
   1573 {
   1574   register const char
   1575     **p,
   1576     **q;
   1577 
   1578   p=(const char **) x;
   1579   q=(const char **) y;
   1580   return(LocaleCompare(*p,*q));
   1581 }
   1582 
   1583 #if defined(__cplusplus) || defined(c_plusplus)
   1584 }
   1585 #endif
   1586 
   1587 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
   1588   struct dirent **result)
   1589 {
   1590 #if defined(MAGICKCORE_HAVE_READDIR_R)
   1591   return(readdir_r(directory,entry,result));
   1592 #else
   1593   (void) entry;
   1594   errno=0;
   1595   *result=readdir(directory);
   1596   return(errno);
   1597 #endif
   1598 }
   1599 
   1600 MagickPrivate char **ListFiles(const char *directory,const char *pattern,
   1601   size_t *number_entries)
   1602 {
   1603   char
   1604     **filelist;
   1605 
   1606   DIR
   1607     *current_directory;
   1608 
   1609   struct dirent
   1610     *buffer,
   1611     *entry;
   1612 
   1613   size_t
   1614     max_entries;
   1615 
   1616   /*
   1617     Open directory.
   1618   */
   1619   assert(directory != (const char *) NULL);
   1620   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
   1621   assert(pattern != (const char *) NULL);
   1622   assert(number_entries != (size_t *) NULL);
   1623   *number_entries=0;
   1624   current_directory=opendir(directory);
   1625   if (current_directory == (DIR *) NULL)
   1626     return((char **) NULL);
   1627   /*
   1628     Allocate filelist.
   1629   */
   1630   max_entries=2048;
   1631   filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
   1632     sizeof(*filelist));
   1633   if (filelist == (char **) NULL)
   1634     {
   1635       (void) closedir(current_directory);
   1636       return((char **) NULL);
   1637     }
   1638   /*
   1639     Save the current and change to the new directory.
   1640   */
   1641   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
   1642   if (buffer == (struct dirent *) NULL)
   1643     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   1644   while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
   1645          (entry != (struct dirent *) NULL))
   1646   {
   1647     if (*entry->d_name == '.')
   1648       continue;
   1649     if ((IsPathDirectory(entry->d_name) > 0) ||
   1650 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
   1651         (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
   1652 #else
   1653         (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
   1654 #endif
   1655       {
   1656         if (*number_entries >= max_entries)
   1657           {
   1658             /*
   1659               Extend the file list.
   1660             */
   1661             max_entries<<=1;
   1662             filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
   1663               max_entries,sizeof(*filelist));
   1664             if (filelist == (char **) NULL)
   1665               break;
   1666           }
   1667 #if defined(vms)
   1668         {
   1669           register char
   1670             *p;
   1671 
   1672           p=strchr(entry->d_name,';');
   1673           if (p)
   1674             *p='\0';
   1675           if (*number_entries > 0)
   1676             if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
   1677               continue;
   1678         }
   1679 #endif
   1680         filelist[*number_entries]=(char *) AcquireString(entry->d_name);
   1681         (*number_entries)++;
   1682       }
   1683   }
   1684   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
   1685   (void) closedir(current_directory);
   1686   if (filelist == (char **) NULL)
   1687     return((char **) NULL);
   1688   /*
   1689     Sort filelist in ascending order.
   1690   */
   1691   qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
   1692     FileCompare);
   1693   return(filelist);
   1694 }
   1695 
   1696 /*
   1698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1699 %                                                                             %
   1700 %                                                                             %
   1701 %                                                                             %
   1702 %   M a g i c k D e l a y                                                     %
   1703 %                                                                             %
   1704 %                                                                             %
   1705 %                                                                             %
   1706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1707 %
   1708 %  MagickDelay() suspends program execution for the number of milliseconds
   1709 %  specified.
   1710 %
   1711 %  The format of the Delay method is:
   1712 %
   1713 %      void MagickDelay(const MagickSizeType milliseconds)
   1714 %
   1715 %  A description of each parameter follows:
   1716 %
   1717 %    o milliseconds: Specifies the number of milliseconds to delay before
   1718 %      returning.
   1719 %
   1720 */
   1721 MagickExport void MagickDelay(const MagickSizeType milliseconds)
   1722 {
   1723   if (milliseconds == 0)
   1724     return;
   1725 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
   1726   {
   1727     struct timespec
   1728       timer;
   1729 
   1730     timer.tv_sec=(time_t) (milliseconds/1000);
   1731     timer.tv_nsec=(milliseconds % 1000)*1000*1000;
   1732     (void) nanosleep(&timer,(struct timespec *) NULL);
   1733   }
   1734 #elif defined(MAGICKCORE_HAVE_USLEEP)
   1735   usleep(1000*milliseconds);
   1736 #elif defined(MAGICKCORE_HAVE_SELECT)
   1737   {
   1738     struct timeval
   1739       timer;
   1740 
   1741     timer.tv_sec=(long) milliseconds/1000;
   1742     timer.tv_usec=(long) (milliseconds % 1000)*1000;
   1743     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
   1744   }
   1745 #elif defined(MAGICKCORE_HAVE_POLL)
   1746   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
   1747 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
   1748   Sleep((long) milliseconds);
   1749 #elif defined(vms)
   1750   {
   1751     float
   1752       timer;
   1753 
   1754     timer=milliseconds/1000.0;
   1755     lib$wait(&timer);
   1756   }
   1757 #elif defined(__BEOS__)
   1758   snooze(1000*milliseconds);
   1759 #else
   1760 # error "Time delay method not defined."
   1761 #endif
   1762 }
   1763 
   1764 /*
   1766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1767 %                                                                             %
   1768 %                                                                             %
   1769 %                                                                             %
   1770 %  M u l t i l i n e C e n s u s                                              %
   1771 %                                                                             %
   1772 %                                                                             %
   1773 %                                                                             %
   1774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1775 %
   1776 %  MultilineCensus() returns the number of lines within a label.  A line is
   1777 %  represented by a \n character.
   1778 %
   1779 %  The format of the MultilineCenus method is:
   1780 %
   1781 %      size_t MultilineCensus(const char *label)
   1782 %
   1783 %  A description of each parameter follows.
   1784 %
   1785 %   o  label:  This character string is the label.
   1786 %
   1787 */
   1788 MagickExport size_t MultilineCensus(const char *label)
   1789 {
   1790   size_t
   1791     number_lines;
   1792 
   1793   /*
   1794     Determine the number of lines within this label.
   1795   */
   1796   if (label == (char *) NULL)
   1797     return(0);
   1798   for (number_lines=1; *label != '\0'; label++)
   1799     if (*label == '\n')
   1800       number_lines++;
   1801   return(number_lines);
   1802 }
   1803 
   1804 /*
   1806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1807 %                                                                             %
   1808 %                                                                             %
   1809 %                                                                             %
   1810 %   S h r e d F i l e                                                         %
   1811 %                                                                             %
   1812 %                                                                             %
   1813 %                                                                             %
   1814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1815 %
   1816 %  ShredFile() overwrites the specified file with zeros or random data and then
   1817 %  removes it.  The overwrite is optional and is only required to help keep
   1818 %  the contents of the file private.  On the first pass, the file is zeroed.
   1819 %  For subsequent passes, random data is written.
   1820 %
   1821 %  The format of the ShredFile method is:
   1822 %
   1823 %      MagickBooleanType ShredFile(const char *path)
   1824 %
   1825 %  A description of each parameter follows.
   1826 %
   1827 %    o path:  Specifies a path to a file.
   1828 %
   1829 */
   1830 MagickPrivate MagickBooleanType ShredFile(const char *path)
   1831 {
   1832   char
   1833     *passes;
   1834 
   1835   int
   1836     file,
   1837     status;
   1838 
   1839   MagickSizeType
   1840     length;
   1841 
   1842   register ssize_t
   1843     i;
   1844 
   1845   size_t
   1846     quantum;
   1847 
   1848   struct stat
   1849     file_stats;
   1850 
   1851   if ((path == (const char *) NULL) || (*path == '\0'))
   1852     return(MagickFalse);
   1853   passes=GetEnvironmentValue("MAGICK_SHRED_PASSES");
   1854   if (passes == (char *) NULL)
   1855     {
   1856       /*
   1857         Don't shred the file, just remove it.
   1858       */
   1859       status=remove_utf8(path);
   1860       if (status == -1)
   1861         {
   1862           (void) LogMagickEvent(ExceptionEvent,GetMagickModule(),
   1863             "Failed to remove: %s",path);
   1864           return(MagickFalse);
   1865         }
   1866       return(MagickTrue);
   1867     }
   1868   file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
   1869   if (file == -1)
   1870     {
   1871       /*
   1872         Don't shred the file, just remove it.
   1873       */
   1874       passes=DestroyString(passes);
   1875       status=remove_utf8(path);
   1876       if (status == -1)
   1877         (void) LogMagickEvent(ExceptionEvent,GetMagickModule(),
   1878           "Failed to remove: %s",path);
   1879       return(MagickFalse);
   1880     }
   1881   /*
   1882     Shred the file.
   1883   */
   1884   quantum=(size_t) MagickMaxBufferExtent;
   1885   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
   1886     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   1887   length=(MagickSizeType) file_stats.st_size;
   1888   for (i=0; i < (ssize_t) StringToInteger(passes); i++)
   1889   {
   1890     RandomInfo
   1891       *random_info;
   1892 
   1893     register MagickOffsetType
   1894       j;
   1895 
   1896     ssize_t
   1897       count;
   1898 
   1899     if (lseek(file,0,SEEK_SET) < 0)
   1900       break;
   1901     random_info=AcquireRandomInfo();
   1902     for (j=0; j < (MagickOffsetType) length; j+=count)
   1903     {
   1904       StringInfo
   1905         *key;
   1906 
   1907       key=GetRandomKey(random_info,quantum);
   1908       if (i == 0)
   1909         ResetStringInfo(key);  /* zero on first pass */
   1910       count=write(file,GetStringInfoDatum(key),(size_t)
   1911         MagickMin(quantum,length-j));
   1912       key=DestroyStringInfo(key);
   1913       if (count <= 0)
   1914         {
   1915           count=0;
   1916           if (errno != EINTR)
   1917             break;
   1918         }
   1919     }
   1920     random_info=DestroyRandomInfo(random_info);
   1921     if (j < (MagickOffsetType) length)
   1922       break;
   1923   }
   1924   status=close(file);
   1925   status=remove_utf8(path);
   1926   if (status != -1)
   1927     status=StringToInteger(passes);
   1928   passes=DestroyString(passes);
   1929   return((status == -1 || i < (ssize_t) status) ? MagickFalse : MagickTrue);
   1930 }
   1931