MagickCore  6.7.5
utility.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
00007 %             U   U    T      I    L        I      T     Y Y                  %
00008 %             U   U    T      I    L        I      T      Y                   %
00009 %             U   U    T      I    L        I      T      Y                   %
00010 %              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
00011 %                                                                             %
00012 %                                                                             %
00013 %                       MagickCore Utility Methods                            %
00014 %                                                                             %
00015 %                             Software Design                                 %
00016 %                               John Cristy                                   %
00017 %                              January 1993                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "MagickCore/studio.h"
00043 #include "MagickCore/property.h"
00044 #include "MagickCore/blob.h"
00045 #include "MagickCore/color.h"
00046 #include "MagickCore/exception.h"
00047 #include "MagickCore/exception-private.h"
00048 #include "MagickCore/geometry.h"
00049 #include "MagickCore/list.h"
00050 #include "MagickCore/log.h"
00051 #include "MagickCore/magick-private.h"
00052 #include "MagickCore/memory_.h"
00053 #include "MagickCore/nt-base-private.h"
00054 #include "MagickCore/option.h"
00055 #include "MagickCore/policy.h"
00056 #include "MagickCore/resource_.h"
00057 #include "MagickCore/semaphore.h"
00058 #include "MagickCore/signature-private.h"
00059 #include "MagickCore/statistic.h"
00060 #include "MagickCore/string_.h"
00061 #include "MagickCore/string-private.h"
00062 #include "MagickCore/token.h"
00063 #include "MagickCore/token-private.h"
00064 #include "MagickCore/utility.h"
00065 #include "MagickCore/utility-private.h"
00066 #if defined(MAGICKCORE_HAVE_PROCESS_H)
00067 #include <process.h>
00068 #endif
00069 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
00070 #include <mach-o/dyld.h>
00071 #endif
00072 
00073 /*
00074   Static declarations.
00075 */
00076 static const char
00077   Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00078 
00079 /*
00080   Forward declaration.
00081 */
00082 static int
00083   IsPathDirectory(const char *);
00084 
00085 /*
00086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00087 %                                                                             %
00088 %                                                                             %
00089 %                                                                             %
00090 %   A c q u i r e U n i q u e F i l e n a m e                                 %
00091 %                                                                             %
00092 %                                                                             %
00093 %                                                                             %
00094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00095 %
00096 %  AcquireUniqueFilename() replaces the contents of path by a unique path name.
00097 %
00098 %  The format of the AcquireUniqueFilename method is:
00099 %
00100 %      MagickBooleanType AcquireUniqueFilename(char *path)
00101 %
00102 %  A description of each parameter follows.
00103 %
00104 %   o  path:  Specifies a pointer to an array of characters.  The unique path
00105 %      name is returned in this array.
00106 %
00107 */
00108 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
00109 {
00110   int
00111     file;
00112 
00113   file=AcquireUniqueFileResource(path);
00114   if (file == -1)
00115     return(MagickFalse);
00116   file=close(file)-1;
00117   return(MagickTrue);
00118 }
00119 
00120 /*
00121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00122 %                                                                             %
00123 %                                                                             %
00124 %                                                                             %
00125 %   A c q u i r e U n i q u e S ym b o l i c L i n k                          %
00126 %                                                                             %
00127 %                                                                             %
00128 %                                                                             %
00129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00130 %
00131 %  AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified
00132 %  source path and returns MagickTrue on success otherwise MagickFalse.  If the
00133 %  symlink() method fails or is not available, a unique file name is generated
00134 %  and the source file copied to it.  When you are finished with the file, use
00135 %  RelinquishUniqueFilename() to destroy it.
00136 %
00137 %  The format of the AcquireUniqueSymbolicLink method is:
00138 %
00139 %      MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
00140 %        char destination)
00141 %
00142 %  A description of each parameter follows.
00143 %
00144 %   o  source:  the source path.
00145 %
00146 %   o  destination:  the destination path.
00147 %
00148 */
00149 
00150 static inline size_t MagickMin(const size_t x,const size_t y)
00151 {
00152   if (x < y)
00153     return(x);
00154   return(y);
00155 }
00156 
00157 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
00158   char *destination)
00159 {
00160   int
00161     destination_file,
00162     source_file;
00163 
00164   size_t
00165     length,
00166     quantum;
00167 
00168   ssize_t
00169     count;
00170 
00171   struct stat
00172     attributes;
00173 
00174   unsigned char
00175     *buffer;
00176 
00177   assert(source != (const char *) NULL);
00178   assert(destination != (char *) NULL);
00179 #if defined(MAGICKCORE_HAVE_SYMLINK)
00180   (void) AcquireUniqueFilename(destination);
00181   (void) RelinquishUniqueFileResource(destination);
00182   if (*source == *DirectorySeparator)
00183     {
00184       if (symlink(source,destination) == 0)
00185         return(MagickTrue);
00186     }
00187   else
00188     {
00189       char
00190         path[MaxTextExtent];
00191 
00192       *path='\0';
00193       if (getcwd(path,MaxTextExtent) == (char *) NULL)
00194         return(MagickFalse);
00195       (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
00196       (void) ConcatenateMagickString(path,source,MaxTextExtent);
00197       if (symlink(path,destination) == 0)
00198         return(MagickTrue);
00199     }
00200 #endif
00201   destination_file=AcquireUniqueFileResource(destination);
00202   if (destination_file == -1)
00203     return(MagickFalse);
00204   source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
00205   if (source_file == -1)
00206     {
00207       (void) close(destination_file);
00208       (void) RelinquishUniqueFileResource(destination);
00209       return(MagickFalse);
00210     }
00211   quantum=(size_t) MagickMaxBufferExtent;
00212   if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
00213     quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
00214   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
00215   if (buffer == (unsigned char *) NULL)
00216     {
00217       (void) close(source_file);
00218       (void) close(destination_file);
00219       (void) RelinquishUniqueFileResource(destination);
00220       return(MagickFalse);
00221     }
00222   for (length=0; ; )
00223   {
00224     count=(ssize_t) read(source_file,buffer,quantum);
00225     if (count <= 0)
00226       break;
00227     length=(size_t) count;
00228     count=(ssize_t) write(destination_file,buffer,length);
00229     if ((size_t) count != length)
00230       {
00231         (void) close(destination_file);
00232         (void) close(source_file);
00233         buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00234         (void) RelinquishUniqueFileResource(destination);
00235         return(MagickFalse);
00236       }
00237   }
00238   (void) close(destination_file);
00239   (void) close(source_file);
00240   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00241   return(MagickTrue);
00242 }
00243 
00244 /*
00245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00246 %                                                                             %
00247 %                                                                             %
00248 %                                                                             %
00249 %  A p p e n d I m a g e F o r m a t                                          %
00250 %                                                                             %
00251 %                                                                             %
00252 %                                                                             %
00253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00254 %
00255 %  AppendImageFormat() appends the image format type to the filename.  If an
00256 %  extension to the file already exists, it is first removed.
00257 %
00258 %  The format of the AppendImageFormat method is:
00259 %
00260 %      void AppendImageFormat(const char *format,char *filename)
00261 %
00262 %  A description of each parameter follows.
00263 %
00264 %   o  format:  Specifies a pointer to an array of characters.  This the
00265 %      format of the image.
00266 %
00267 %   o  filename:  Specifies a pointer to an array of characters.  The unique
00268 %      file name is returned in this array.
00269 %
00270 */
00271 MagickExport void AppendImageFormat(const char *format,char *filename)
00272 {
00273   char
00274     extension[MaxTextExtent],
00275     root[MaxTextExtent];
00276 
00277   assert(format != (char *) NULL);
00278   assert(filename != (char *) NULL);
00279   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00280   if ((*format == '\0') || (*filename == '\0'))
00281     return;
00282   if (LocaleCompare(filename,"-") == 0)
00283     {
00284       char
00285         message[MaxTextExtent];
00286 
00287       (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",format,filename);
00288       (void) CopyMagickString(filename,message,MaxTextExtent);
00289       return;
00290     }
00291   GetPathComponent(filename,ExtensionPath,extension);
00292   if ((LocaleCompare(extension,"Z") == 0) ||
00293       (LocaleCompare(extension,"bz2") == 0) ||
00294       (LocaleCompare(extension,"gz") == 0) ||
00295       (LocaleCompare(extension,"wmz") == 0) ||
00296       (LocaleCompare(extension,"svgz") == 0))
00297     {
00298       GetPathComponent(filename,RootPath,root);
00299       (void) CopyMagickString(filename,root,MaxTextExtent);
00300       GetPathComponent(filename,RootPath,root);
00301       (void) FormatLocaleString(filename,MaxTextExtent,"%s.%s.%s",root,format,
00302         extension);
00303       return;
00304     }
00305   GetPathComponent(filename,RootPath,root);
00306   (void) FormatLocaleString(filename,MaxTextExtent,"%s.%s",root,format);
00307 }
00308 
00309 /*
00310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00311 %                                                                             %
00312 %                                                                             %
00313 %                                                                             %
00314 %   B a s e 6 4 D e c o d e                                                   %
00315 %                                                                             %
00316 %                                                                             %
00317 %                                                                             %
00318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00319 %
00320 %  Base64Decode() decodes Base64-encoded text and returns its binary
00321 %  equivalent.  NULL is returned if the text is not valid Base64 data, or a
00322 %  memory allocation failure occurs.
00323 %
00324 %  The format of the Base64Decode method is:
00325 %
00326 %      unsigned char *Base64Decode(const char *source,length_t *length)
00327 %
00328 %  A description of each parameter follows:
00329 %
00330 %    o source:  A pointer to a Base64-encoded string.
00331 %
00332 %    o length: the number of bytes decoded.
00333 %
00334 */
00335 MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
00336 {
00337   int
00338     state;
00339 
00340   register const char
00341     *p,
00342     *q;
00343 
00344   register size_t
00345     i;
00346 
00347   unsigned char
00348     *decode;
00349 
00350   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00351   assert(source != (char *) NULL);
00352   assert(length != (size_t *) NULL);
00353   *length=0;
00354   decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
00355     3*sizeof(*decode));
00356   if (decode == (unsigned char *) NULL)
00357     return((unsigned char *) NULL);
00358   i=0;
00359   state=0;
00360   for (p=source; *p != '\0'; p++)
00361   {
00362     if (isspace((int) ((unsigned char) *p)) != 0)
00363       continue;
00364     if (*p == '=')
00365       break;
00366     q=strchr(Base64,*p);
00367     if (q == (char *) NULL)
00368       {
00369         decode=(unsigned char *) RelinquishMagickMemory(decode);
00370         return((unsigned char *) NULL);  /* non-Base64 character */
00371       }
00372     switch (state)
00373     {
00374       case 0:
00375       {
00376         decode[i]=(q-Base64) << 2;
00377         state++;
00378         break;
00379       }
00380       case 1:
00381       {
00382         decode[i++]|=(q-Base64) >> 4;
00383         decode[i]=((q-Base64) & 0x0f) << 4;
00384         state++;
00385         break;
00386       }
00387       case 2:
00388       {
00389         decode[i++]|=(q-Base64) >> 2;
00390         decode[i]=((q-Base64) & 0x03) << 6;
00391         state++;
00392         break;
00393       }
00394       case 3:
00395       {
00396         decode[i++]|=(q-Base64);
00397         state=0;
00398         break;
00399       }
00400     }
00401   }
00402   /*
00403     Verify Base-64 string has proper terminal characters.
00404   */
00405   if (*p != '=')
00406     {
00407       if (state != 0)
00408         {
00409           decode=(unsigned char *) RelinquishMagickMemory(decode);
00410           return((unsigned char *) NULL);
00411         }
00412     }
00413   else
00414     {
00415       p++;
00416       switch (state)
00417       {
00418         case 0:
00419         case 1:
00420         {
00421           /*
00422             Unrecognized '=' character.
00423           */
00424           decode=(unsigned char *) RelinquishMagickMemory(decode);
00425           return((unsigned char *) NULL);
00426         }
00427         case 2:
00428         {
00429           for ( ; *p != '\0'; p++)
00430             if (isspace((int) ((unsigned char) *p)) == 0)
00431               break;
00432           if (*p != '=')
00433             {
00434               decode=(unsigned char *) RelinquishMagickMemory(decode);
00435               return((unsigned char *) NULL);
00436             }
00437           p++;
00438         }
00439         case 3:
00440         {
00441           for ( ; *p != '\0'; p++)
00442             if (isspace((int) ((unsigned char) *p)) == 0)
00443               {
00444                 decode=(unsigned char *) RelinquishMagickMemory(decode);
00445                 return((unsigned char *) NULL);
00446               }
00447           if ((int) decode[i] != 0)
00448             {
00449               decode=(unsigned char *) RelinquishMagickMemory(decode);
00450               return((unsigned char *) NULL);
00451             }
00452         }
00453       }
00454     }
00455   *length=i;
00456   return(decode);
00457 }
00458 
00459 /*
00460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00461 %                                                                             %
00462 %                                                                             %
00463 %                                                                             %
00464 %   B a s e 6 4 E n c o d e                                                   %
00465 %                                                                             %
00466 %                                                                             %
00467 %                                                                             %
00468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00469 %
00470 %  Base64Encode() encodes arbitrary binary data to Base64 encoded format as
00471 %  described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and
00472 %  returns the result as a null-terminated ASCII string.  NULL is returned if
00473 %  a memory allocation failure occurs.
00474 %
00475 %  The format of the Base64Encode method is:
00476 %
00477 %      char *Base64Encode(const unsigned char *blob,const size_t blob_length,
00478 %        size_t *encode_length)
00479 %
00480 %  A description of each parameter follows:
00481 %
00482 %    o blob:  A pointer to binary data to encode.
00483 %
00484 %    o blob_length: the number of bytes to encode.
00485 %
00486 %    o encode_length:  The number of bytes encoded.
00487 %
00488 */
00489 MagickExport char *Base64Encode(const unsigned char *blob,
00490   const size_t blob_length,size_t *encode_length)
00491 {
00492   char
00493     *encode;
00494 
00495   register const unsigned char
00496     *p;
00497 
00498   register size_t
00499     i;
00500 
00501   size_t
00502     remainder;
00503 
00504   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00505   assert(blob != (const unsigned char *) NULL);
00506   assert(blob_length != 0);
00507   assert(encode_length != (size_t *) NULL);
00508   *encode_length=0;
00509   encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
00510   if (encode == (char *) NULL)
00511     return((char *) NULL);
00512   i=0;
00513   for (p=blob; p < (blob+blob_length-2); p+=3)
00514   {
00515     encode[i++]=Base64[(int) (*p >> 2)];
00516     encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
00517     encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
00518     encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
00519   }
00520   remainder=blob_length % 3;
00521   if (remainder != 0)
00522     {
00523       ssize_t
00524         j;
00525 
00526       unsigned char
00527         code[3];
00528 
00529       code[0]='\0';
00530       code[1]='\0';
00531       code[2]='\0';
00532       for (j=0; j < (ssize_t) remainder; j++)
00533         code[j]=(*p++);
00534       encode[i++]=Base64[(int) (code[0] >> 2)];
00535       encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
00536       if (remainder == 1)
00537         encode[i++]='=';
00538       else
00539         encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
00540       encode[i++]='=';
00541     }
00542   *encode_length=i;
00543   encode[i++]='\0';
00544   return(encode);
00545 }
00546 
00547 /*
00548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00549 %                                                                             %
00550 %                                                                             %
00551 %                                                                             %
00552 %   C h o p P a t h C o m p o n e n t s                                       %
00553 %                                                                             %
00554 %                                                                             %
00555 %                                                                             %
00556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00557 %
00558 %  ChopPathComponents() removes the number of specified file components from a
00559 %  path.
00560 %
00561 %  The format of the ChopPathComponents method is:
00562 %
00563 %      ChopPathComponents(char *path,size_t components)
00564 %
00565 %  A description of each parameter follows:
00566 %
00567 %    o path:  The path.
00568 %
00569 %    o components:  The number of components to chop.
00570 %
00571 */
00572 MagickPrivate void ChopPathComponents(char *path,const size_t components)
00573 {
00574   register ssize_t
00575     i;
00576 
00577   for (i=0; i < (ssize_t) components; i++)
00578     GetPathComponent(path,HeadPath,path);
00579 }
00580 
00581 /*
00582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00583 %                                                                             %
00584 %                                                                             %
00585 %                                                                             %
00586 %   E x p a n d F i l e n a m e                                               %
00587 %                                                                             %
00588 %                                                                             %
00589 %                                                                             %
00590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00591 %
00592 %  ExpandFilename() expands '~' in a path.
00593 %
00594 %  The format of the ExpandFilename function is:
00595 %
00596 %      ExpandFilename(char *path)
00597 %
00598 %  A description of each parameter follows:
00599 %
00600 %    o path: Specifies a pointer to a character array that contains the
00601 %      path.
00602 %
00603 */
00604 MagickPrivate void ExpandFilename(char *path)
00605 {
00606   char
00607     expand_path[MaxTextExtent];
00608 
00609   if (path == (char *) NULL)
00610     return;
00611   if (*path != '~')
00612     return;
00613   (void) CopyMagickString(expand_path,path,MaxTextExtent);
00614   if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
00615     {
00616       char
00617         *home;
00618 
00619       /*
00620         Substitute ~ with $HOME.
00621       */
00622       (void) CopyMagickString(expand_path,".",MaxTextExtent);
00623       (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00624       home=GetEnvironmentValue("HOME");
00625       if (home == (char *) NULL)
00626         home=GetEnvironmentValue("USERPROFILE");
00627       if (home != (char *) NULL)
00628         {
00629           (void) CopyMagickString(expand_path,home,MaxTextExtent);
00630           (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00631           home=DestroyString(home);
00632         }
00633     }
00634   else
00635     {
00636 #if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
00637       char
00638         username[MaxTextExtent];
00639 
00640       register char
00641         *p;
00642 
00643       struct passwd
00644         *entry;
00645 
00646       /*
00647         Substitute ~ with home directory from password file.
00648       */
00649       (void) CopyMagickString(username,path+1,MaxTextExtent);
00650       p=strchr(username,'/');
00651       if (p != (char *) NULL)
00652         *p='\0';
00653       entry=getpwnam(username);
00654       if (entry == (struct passwd *) NULL)
00655         return;
00656       (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
00657       if (p != (char *) NULL)
00658         {
00659           (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
00660           (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
00661         }
00662 #endif
00663     }
00664   (void) CopyMagickString(path,expand_path,MaxTextExtent);
00665 }
00666 
00667 /*
00668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00669 %                                                                             %
00670 %                                                                             %
00671 %                                                                             %
00672 %   E x p a n d F i l e n a m e s                                             %
00673 %                                                                             %
00674 %                                                                             %
00675 %                                                                             %
00676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00677 %
00678 %  ExpandFilenames() checks each argument of the command line vector and
00679 %  expands it if they have a wildcard character.  For example, *.jpg might
00680 %  expand to:  bird.jpg rose.jpg tiki.jpg.
00681 %
00682 %  The format of the ExpandFilenames function is:
00683 %
00684 %      status=ExpandFilenames(int *number_arguments,char ***arguments)
00685 %
00686 %  A description of each parameter follows:
00687 %
00688 %    o number_arguments: Specifies a pointer to an integer describing the
00689 %      number of elements in the argument vector.
00690 %
00691 %    o arguments: Specifies a pointer to a text array containing the command
00692 %      line arguments.
00693 %
00694 */
00695 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
00696   char ***arguments)
00697 {
00698   char
00699     *directory,
00700     home_directory[MaxTextExtent],
00701     **vector;
00702 
00703   register ssize_t
00704     i,
00705     j;
00706 
00707   size_t
00708     number_files;
00709 
00710   ssize_t
00711     count,
00712     parameters;
00713 
00714   /*
00715     Allocate argument vector.
00716   */
00717   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00718   assert(number_arguments != (int *) NULL);
00719   assert(arguments != (char ***) NULL);
00720   vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
00721     sizeof(*vector));
00722   if (vector == (char **) NULL)
00723     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00724   /*
00725     Expand any wildcard filenames.
00726   */
00727   *home_directory='\0';
00728   count=0;
00729   for (i=0; i < (ssize_t) *number_arguments; i++)
00730   {
00731     char
00732       **filelist,
00733       filename[MaxTextExtent],
00734       magick[MaxTextExtent],
00735       *option,
00736       path[MaxTextExtent],
00737       subimage[MaxTextExtent];
00738 
00739     MagickBooleanType
00740       destroy;
00741 
00742     option=(*arguments)[i];
00743     *magick='\0';
00744     *path='\0';
00745     *filename='\0';
00746     *subimage='\0';
00747     vector[count++]=ConstantString(option);
00748     destroy=MagickTrue;
00749     parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
00750     if (parameters > 0)
00751       {
00752         /*
00753           Do not expand command option parameters.
00754         */
00755         for (j=0; j < parameters; j++)
00756         {
00757           i++;
00758           if (i == (ssize_t) *number_arguments)
00759             break;
00760           option=(*arguments)[i];
00761           vector[count++]=ConstantString(option);
00762         }
00763         continue;
00764       }
00765     if ((*option == '"') || (*option == '\''))
00766       continue;
00767     GetPathComponent(option,TailPath,filename);
00768     GetPathComponent(option,MagickPath,magick);
00769     if ((LocaleCompare(magick,"CAPTION") == 0) ||
00770         (LocaleCompare(magick,"LABEL") == 0) ||
00771         (LocaleCompare(magick,"VID") == 0))
00772       continue;
00773     if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
00774       continue;
00775     if (*filename != '@')
00776       {
00777         /*
00778           Generate file list from wildcard filename (e.g. *.jpg).
00779         */
00780         GetPathComponent(option,HeadPath,path);
00781         GetPathComponent(option,SubimagePath,subimage);
00782         ExpandFilename(path);
00783         if (*home_directory == '\0')
00784           directory=getcwd(home_directory,MaxTextExtent-1);
00785         (void) directory;
00786         filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
00787           &number_files);
00788       }
00789     else
00790       {
00791         char
00792           *files;
00793 
00794         ExceptionInfo
00795           *exception;
00796 
00797         int
00798           length;
00799 
00800         /*
00801           Generate file list from file list (e.g. @filelist.txt).
00802         */
00803         exception=AcquireExceptionInfo();
00804         files=FileToString(filename+1,~0,exception);
00805         exception=DestroyExceptionInfo(exception);
00806         if (files == (char *) NULL)
00807           continue;
00808         filelist=StringToArgv(files,&length);
00809         if (filelist == (char **) NULL)
00810           continue;
00811         files=DestroyString(files);
00812         filelist[0]=DestroyString(filelist[0]);
00813         for (j=0; j < (ssize_t) (length-1); j++)
00814           filelist[j]=filelist[j+1];
00815         number_files=(size_t) length-1;
00816       }
00817     if (filelist == (char **) NULL)
00818       continue;
00819     for (j=0; j < (ssize_t) number_files; j++)
00820       if (IsPathDirectory(filelist[j]) <= 0)
00821         break;
00822     if (j == (ssize_t) number_files)
00823       {
00824         for (j=0; j < (ssize_t) number_files; j++)
00825           filelist[j]=DestroyString(filelist[j]);
00826         filelist=(char **) RelinquishMagickMemory(filelist);
00827         continue;
00828       }
00829     /*
00830       Transfer file list to argument vector.
00831     */
00832     vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
00833       count+number_files+1,sizeof(*vector));
00834     if (vector == (char **) NULL)
00835       return(MagickFalse);
00836     for (j=0; j < (ssize_t) number_files; j++)
00837     {
00838       option=filelist[j];
00839       parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
00840       if (parameters > 0)
00841         {
00842           ssize_t
00843             k;
00844 
00845           /*
00846             Do not expand command option parameters.
00847           */
00848           vector[count++]=ConstantString(option);
00849           for (k=0; k < parameters; k++)
00850           {
00851             j++;
00852             if (j == (ssize_t) number_files)
00853               break;
00854             option=filelist[j];
00855             vector[count++]=ConstantString(option);
00856           }
00857           continue;
00858         }
00859       (void) CopyMagickString(filename,path,MaxTextExtent);
00860       if (*path != '\0')
00861         (void) ConcatenateMagickString(filename,DirectorySeparator,
00862           MaxTextExtent);
00863       (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
00864       filelist[j]=DestroyString(filelist[j]);
00865       if (strlen(filename) >= (MaxTextExtent-1))
00866         ThrowFatalException(OptionFatalError,"FilenameTruncated");
00867       if (IsPathDirectory(filename) <= 0)
00868         {
00869           char
00870             path[MaxTextExtent];
00871 
00872           *path='\0';
00873           if (*magick != '\0')
00874             {
00875               (void) ConcatenateMagickString(path,magick,MaxTextExtent);
00876               (void) ConcatenateMagickString(path,":",MaxTextExtent);
00877             }
00878           (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00879           if (*subimage != '\0')
00880             {
00881               (void) ConcatenateMagickString(path,"[",MaxTextExtent);
00882               (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
00883               (void) ConcatenateMagickString(path,"]",MaxTextExtent);
00884             }
00885           if (strlen(path) >= (MaxTextExtent-1))
00886             ThrowFatalException(OptionFatalError,"FilenameTruncated");
00887           if (destroy != MagickFalse)
00888             {
00889               count--;
00890               vector[count]=DestroyString(vector[count]);
00891               destroy=MagickFalse;
00892             }
00893           vector[count++]=ConstantString(path);
00894         }
00895     }
00896     filelist=(char **) RelinquishMagickMemory(filelist);
00897   }
00898   vector[count]=(char *) NULL;
00899   if (IsEventLogging() != MagickFalse)
00900     {
00901       char
00902         *command_line;
00903 
00904       command_line=AcquireString(vector[0]);
00905       for (i=1; i < count; i++)
00906       {
00907         (void) ConcatenateString(&command_line," {");
00908         (void) ConcatenateString(&command_line,vector[i]);
00909         (void) ConcatenateString(&command_line,"}");
00910       }
00911       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00912         "Command line: %s",command_line);
00913       command_line=DestroyString(command_line);
00914     }
00915   *number_arguments=(int) count;
00916   *arguments=vector;
00917   return(MagickTrue);
00918 }
00919 
00920 /*
00921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00922 %                                                                             %
00923 %                                                                             %
00924 %                                                                             %
00925 %   G e t E x e c u t i o n P a t h                                           %
00926 %                                                                             %
00927 %                                                                             %
00928 %                                                                             %
00929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00930 %
00931 %  GetExecutionPath() returns the pathname of the executable that started
00932 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
00933 %
00934 %  The format of the GetExecutionPath method is:
00935 %
00936 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00937 %
00938 %  A description of each parameter follows:
00939 %
00940 %    o path: the pathname of the executable that started the process.
00941 %
00942 %    o extent: the maximum extent of the path.
00943 %
00944 */
00945 MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00946 {
00947   char
00948     *directory;
00949 
00950   *path='\0';
00951   directory=getcwd(path,(unsigned long) extent);
00952   (void) directory;
00953 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
00954   {
00955     char
00956       link_path[MaxTextExtent],
00957       execution_path[PATH_MAX+1];
00958 
00959     ssize_t
00960       count;
00961 
00962     (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe",
00963       (double) getpid());
00964     count=readlink(link_path,execution_path,PATH_MAX);
00965     if (count == -1)
00966       {
00967         (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file",
00968           (double) getpid());
00969         count=readlink(link_path,execution_path,PATH_MAX);
00970       }
00971     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
00972       {
00973         execution_path[count]='\0';
00974         (void) CopyMagickString(path,execution_path,extent);
00975       }
00976   }
00977 #endif
00978 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
00979   {
00980     char
00981       executable_path[PATH_MAX << 1],
00982       execution_path[PATH_MAX+1];
00983 
00984     uint32_t
00985       length;
00986 
00987     length=sizeof(executable_path);
00988     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
00989         (realpath(executable_path,execution_path) != (char *) NULL))
00990       (void) CopyMagickString(path,execution_path,extent);
00991   }
00992 #endif
00993 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
00994   {
00995     const char
00996       *execution_path;
00997 
00998     execution_path=(const char *) getexecname();
00999     if (execution_path != (const char *) NULL)
01000       {
01001         if (*execution_path != *DirectorySeparator)
01002           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
01003         (void) ConcatenateMagickString(path,execution_path,extent);
01004       }
01005   }
01006 #endif
01007 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
01008   NTGetExecutionPath(path,extent);
01009 #endif
01010 #if defined(__GNU__)
01011   {
01012     char
01013       *program_name,
01014       *execution_path;
01015 
01016     ssize_t
01017       count;
01018 
01019     count=0;
01020     execution_path=(char *) NULL;
01021     program_name=program_invocation_name;
01022     if (*program_invocation_name != '/')
01023       {
01024         size_t
01025           extent;
01026 
01027         extent=strlen(directory)+strlen(program_name)+2;
01028         program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
01029         if (program_name == (char *) NULL)
01030           program_name=program_invocation_name;
01031         else
01032           count=FormatLocaleString(program_name,extent,"%s/%s",directory,
01033             program_invocation_name);
01034       }
01035     if (count != -1)
01036       {
01037         execution_path=realpath(program_name,NULL);
01038         if (execution_path != (char *) NULL)
01039           (void) CopyMagickString(path,execution_path,extent);
01040       }
01041     if (program_name != program_invocation_name)
01042       program_name=(char *) RelinquishMagickMemory(program_name);
01043     execution_path=(char *) RelinquishMagickMemory(execution_path);
01044   }
01045 #endif
01046   return(IsPathAccessible(path));
01047 }
01048 
01049 /*
01050 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01051 %                                                                             %
01052 %                                                                             %
01053 %                                                                             %
01054 %   G e t M a g i c k P a g e S i z e                                         %
01055 %                                                                             %
01056 %                                                                             %
01057 %                                                                             %
01058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01059 %
01060 %  GetMagickPageSize() returns the memory page size.
01061 %
01062 %  The format of the GetMagickPageSize method is:
01063 %
01064 %      ssize_t GetMagickPageSize()
01065 %
01066 */
01067 MagickPrivate ssize_t GetMagickPageSize(void)
01068 {
01069   static ssize_t
01070     page_size = -1;
01071 
01072   if (page_size > 0)
01073     return(page_size);
01074 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
01075   page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
01076 #else
01077 #if defined(MAGICKCORE_HAVE_GETPAGESIZE)
01078   page_size=(ssize_t) getpagesize();
01079 #endif
01080 #endif
01081   if (page_size <= 0)
01082     page_size=16384;
01083   return(page_size);
01084 }
01085 
01086 /*
01087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01088 %                                                                             %
01089 %                                                                             %
01090 %                                                                             %
01091 %   G e t P a t h A t t r i b u t e s                                         %
01092 %                                                                             %
01093 %                                                                             %
01094 %                                                                             %
01095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01096 %
01097 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
01098 %
01099 %  The path of the GetPathAttributes method is:
01100 %
01101 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
01102 %
01103 %  A description of each parameter follows.
01104 %
01105 %   o  path: the file path.
01106 %
01107 %   o  attributes: the path attributes are returned here.
01108 %
01109 */
01110 MagickExport MagickBooleanType GetPathAttributes(const char *path,
01111   void *attributes)
01112 {
01113   MagickBooleanType
01114     status;
01115 
01116   if (path == (const char *) NULL)
01117     {
01118       errno=EINVAL;
01119       return(MagickFalse);
01120     }
01121   status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
01122     MagickFalse;
01123   return(status);
01124 }
01125 
01126 /*
01127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01128 %                                                                             %
01129 %                                                                             %
01130 %                                                                             %
01131 %   G e t P a t h C o m p o n e n t                                           %
01132 %                                                                             %
01133 %                                                                             %
01134 %                                                                             %
01135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01136 %
01137 %  GetPathComponent() returns the parent directory name, filename, basename, or
01138 %  extension of a file path.
01139 %
01140 %  The format of the GetPathComponent function is:
01141 %
01142 %      GetPathComponent(const char *path,PathType type,char *component)
01143 %
01144 %  A description of each parameter follows:
01145 %
01146 %    o path: Specifies a pointer to a character array that contains the
01147 %      file path.
01148 %
01149 %    o type: Specififies which file path component to return.
01150 %
01151 %    o component: the selected file path component is returned here.
01152 %
01153 */
01154 MagickExport void GetPathComponent(const char *path,PathType type,
01155   char *component)
01156 {
01157   char
01158     magick[MaxTextExtent],
01159     *q,
01160     subimage[MaxTextExtent];
01161 
01162   register char
01163     *p;
01164 
01165   assert(path != (const char *) NULL);
01166   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
01167   assert(component != (char *) NULL);
01168   if (*path == '\0')
01169     {
01170       *component='\0';
01171       return;
01172     }
01173   (void) CopyMagickString(component,path,MaxTextExtent);
01174   *magick='\0';
01175 #if defined(__OS2__)
01176   if (path[1] != ":")
01177 #endif
01178   for (p=component; *p != '\0'; p++)
01179   {
01180     if ((*p == '%') && (*(p+1) == '['))
01181       {
01182         /*
01183           Skip over %[...].
01184         */
01185         for (p++; (*p != ']') && (*p != '\0'); p++) ;
01186         if (*p == '\0')
01187           break;
01188       }
01189     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
01190         (IsPathAccessible(path) == MagickFalse))
01191       {
01192         /*
01193           Look for image format specification (e.g. ps3:image).
01194         */
01195         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
01196         if (IsMagickConflict(magick) != MagickFalse)
01197           *magick='\0';
01198         else
01199           for (q=component; *q != '\0'; q++)
01200             *q=(*++p);
01201         break;
01202       }
01203   }
01204   *subimage='\0';
01205   p=component;
01206   if (*p != '\0')
01207     p=component+strlen(component)-1;
01208   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
01209       (IsPathAccessible(path) == MagickFalse))
01210     {
01211       /*
01212         Look for scene specification (e.g. img0001.pcd[4]).
01213       */
01214       for (q=p-1; q > component; q--)
01215         if (*q == '[')
01216           break;
01217       if (*q == '[')
01218         {
01219           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
01220           subimage[p-q-1]='\0';
01221           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
01222               (IsGeometry(subimage) == MagickFalse))
01223             *subimage='\0';
01224           else
01225             *q='\0';
01226         }
01227     }
01228   p=component;
01229   if (*p != '\0')
01230     for (p=component+strlen(component)-1; p > component; p--)
01231       if (IsBasenameSeparator(*p) != MagickFalse)
01232         break;
01233   switch (type)
01234   {
01235     case MagickPath:
01236     {
01237       (void) CopyMagickString(component,magick,MaxTextExtent);
01238       break;
01239     }
01240     case RootPath:
01241     {
01242       for (p=component+(strlen(component)-1); p > component; p--)
01243       {
01244         if (IsBasenameSeparator(*p) != MagickFalse)
01245           break;
01246         if (*p == '.')
01247           break;
01248       }
01249       if (*p == '.')
01250         *p='\0';
01251       break;
01252     }
01253     case HeadPath:
01254     {
01255       *p='\0';
01256       break;
01257     }
01258     case TailPath:
01259     {
01260       if (IsBasenameSeparator(*p) != MagickFalse)
01261         (void) CopyMagickMemory((unsigned char *) component,
01262           (const unsigned char *) (p+1),strlen(p+1)+1);
01263       break;
01264     }
01265     case BasePath:
01266     {
01267       if (IsBasenameSeparator(*p) != MagickFalse)
01268         (void) CopyMagickString(component,p+1,MaxTextExtent);
01269       for (p=component+(strlen(component)-1); p > component; p--)
01270         if (*p == '.')
01271           {
01272             *p='\0';
01273             break;
01274           }
01275       break;
01276     }
01277     case ExtensionPath:
01278     {
01279       if (IsBasenameSeparator(*p) != MagickFalse)
01280         (void) CopyMagickString(component,p+1,MaxTextExtent);
01281       p=component;
01282       if (*p != '\0')
01283         for (p=component+strlen(component)-1; p > component; p--)
01284           if (*p == '.')
01285             break;
01286       *component='\0';
01287       if (*p == '.')
01288         (void) CopyMagickString(component,p+1,MaxTextExtent);
01289       break;
01290     }
01291     case SubimagePath:
01292     {
01293       (void) CopyMagickString(component,subimage,MaxTextExtent);
01294       break;
01295     }
01296     case CanonicalPath:
01297     case UndefinedPath:
01298       break;
01299   }
01300 }
01301 
01302 /*
01303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01304 %                                                                             %
01305 %                                                                             %
01306 %                                                                             %
01307 %  G e t P a t h C o m p o n e n t s                                          %
01308 %                                                                             %
01309 %                                                                             %
01310 %                                                                             %
01311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01312 %
01313 %  GetPathComponents() returns a list of path components.
01314 %
01315 %  The format of the GetPathComponents method is:
01316 %
01317 %      char **GetPathComponents(const char *path,
01318 %        size_t *number_componenets)
01319 %
01320 %  A description of each parameter follows:
01321 %
01322 %    o path:  Specifies the string to segment into a list.
01323 %
01324 %    o number_components:  return the number of components in the list
01325 %
01326 */
01327 MagickPrivate char **GetPathComponents(const char *path,
01328   size_t *number_components)
01329 {
01330   char
01331     **components;
01332 
01333   register const char
01334     *p,
01335     *q;
01336 
01337   register ssize_t
01338     i;
01339 
01340   if (path == (char *) NULL)
01341     return((char **) NULL);
01342   *number_components=1;
01343   for (p=path; *p != '\0'; p++)
01344     if (IsBasenameSeparator(*p))
01345       (*number_components)++;
01346   components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
01347     sizeof(*components));
01348   if (components == (char **) NULL)
01349     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01350   p=path;
01351   for (i=0; i < (ssize_t) *number_components; i++)
01352   {
01353     for (q=p; *q != '\0'; q++)
01354       if (IsBasenameSeparator(*q))
01355         break;
01356     components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
01357       sizeof(**components));
01358     if (components[i] == (char *) NULL)
01359       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01360     (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
01361     p=q+1;
01362   }
01363   components[i]=(char *) NULL;
01364   return(components);
01365 }
01366 
01367 /*
01368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01369 %                                                                             %
01370 %                                                                             %
01371 %                                                                             %
01372 %  I s P a t h A c c e s s i b l e                                            %
01373 %                                                                             %
01374 %                                                                             %
01375 %                                                                             %
01376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01377 %
01378 %  IsPathAccessible() returns MagickTrue if the file as defined by the path is
01379 %  accessible.
01380 %
01381 %  The format of the IsPathAccessible method is:
01382 %
01383 %      MagickBooleanType IsPathAccessible(const char *filename)
01384 %
01385 %  A description of each parameter follows.
01386 %
01387 %    o path:  Specifies a path to a file.
01388 %
01389 */
01390 MagickExport MagickBooleanType IsPathAccessible(const char *path)
01391 {
01392   MagickBooleanType
01393     status;
01394 
01395   struct stat
01396     attributes;
01397 
01398   if ((path == (const char *) NULL) || (*path == '\0'))
01399     return(MagickFalse);
01400   status=GetPathAttributes(path,&attributes);
01401   if (status == MagickFalse)
01402     return(status);
01403   if (S_ISREG(attributes.st_mode) == 0)
01404     return(MagickFalse);
01405   if (access_utf8(path,F_OK) != 0)
01406     return(MagickFalse);
01407   return(MagickTrue);
01408 }
01409 
01410 /*
01411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01412 %                                                                             %
01413 %                                                                             %
01414 %                                                                             %
01415 +  I s P a t h D i r e c t o r y                                              %
01416 %                                                                             %
01417 %                                                                             %
01418 %                                                                             %
01419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01420 %
01421 %  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
01422 %  if the path represents a directory otherwise 0.
01423 %
01424 %  The format of the IsPathDirectory method is:
01425 %
01426 %      int IsPathDirectory(const char *path)
01427 %
01428 %  A description of each parameter follows.
01429 %
01430 %   o  path:  The directory path.
01431 %
01432 */
01433 static int IsPathDirectory(const char *path)
01434 {
01435   MagickBooleanType
01436     status;
01437 
01438   struct stat
01439     attributes;
01440 
01441   if ((path == (const char *) NULL) || (*path == '\0'))
01442     return(MagickFalse);
01443   status=GetPathAttributes(path,&attributes);
01444   if (status == MagickFalse)
01445     return(-1);
01446   if (S_ISDIR(attributes.st_mode) == 0)
01447     return(0);
01448   return(1);
01449 }
01450 
01451 /*
01452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01453 %                                                                             %
01454 %                                                                             %
01455 %                                                                             %
01456 %   I s M a g i c k T r u e                                                   %
01457 %                                                                             %
01458 %                                                                             %
01459 %                                                                             %
01460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01461 %
01462 %  IsMagickTrue() returns MagickTrue if the value is "true", "on", "yes" or
01463 %  "1".
01464 %
01465 %  The format of the IsMagickTrue method is:
01466 %
01467 %      MagickBooleanType IsMagickTrue(const char *value)
01468 %
01469 %  A description of each parameter follows:
01470 %
01471 %    o option: either MagickTrue or MagickFalse depending on the value
01472 %      parameter.
01473 %
01474 %    o value: Specifies a pointer to a character array.
01475 %
01476 */
01477 MagickExport MagickBooleanType IsMagickTrue(const char *value)
01478 {
01479   if (value == (const char *) NULL)
01480     return(MagickFalse);
01481   if (LocaleCompare(value,"true") == 0)
01482     return(MagickTrue);
01483   if (LocaleCompare(value,"on") == 0)
01484     return(MagickTrue);
01485   if (LocaleCompare(value,"yes") == 0)
01486     return(MagickTrue);
01487   if (LocaleCompare(value,"1") == 0)
01488     return(MagickTrue);
01489   return(MagickFalse);
01490 }
01491 
01492 /*
01493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01494 %                                                                             %
01495 %                                                                             %
01496 %                                                                             %
01497 %   L i s t F i l e s                                                         %
01498 %                                                                             %
01499 %                                                                             %
01500 %                                                                             %
01501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01502 %
01503 %  ListFiles() reads the directory specified and returns a list of filenames
01504 %  contained in the directory sorted in ascending alphabetic order.
01505 %
01506 %  The format of the ListFiles function is:
01507 %
01508 %      char **ListFiles(const char *directory,const char *pattern,
01509 %        ssize_t *number_entries)
01510 %
01511 %  A description of each parameter follows:
01512 %
01513 %    o filelist: Method ListFiles returns a list of filenames contained
01514 %      in the directory.  If the directory specified cannot be read or it is
01515 %      a file a NULL list is returned.
01516 %
01517 %    o directory: Specifies a pointer to a text string containing a directory
01518 %      name.
01519 %
01520 %    o pattern: Specifies a pointer to a text string containing a pattern.
01521 %
01522 %    o number_entries:  This integer returns the number of filenames in the
01523 %      list.
01524 %
01525 */
01526 
01527 #if defined(__cplusplus) || defined(c_plusplus)
01528 extern "C" {
01529 #endif
01530 
01531 static int FileCompare(const void *x,const void *y)
01532 {
01533   register const char
01534     **p,
01535     **q;
01536 
01537   p=(const char **) x;
01538   q=(const char **) y;
01539   return(LocaleCompare(*p,*q));
01540 }
01541 
01542 #if defined(__cplusplus) || defined(c_plusplus)
01543 }
01544 #endif
01545 
01546 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
01547   struct dirent **result)
01548 {
01549 #if defined(MAGICKCORE_HAVE_READDIR_R)
01550   return(readdir_r(directory,entry,result));
01551 #else
01552   (void) entry;
01553   errno=0;
01554   *result=readdir(directory);
01555   return(errno);
01556 #endif
01557 }
01558 
01559 MagickPrivate char **ListFiles(const char *directory,const char *pattern,
01560   size_t *number_entries)
01561 {
01562   char
01563     **filelist;
01564 
01565   DIR
01566     *current_directory;
01567 
01568   struct dirent
01569     *buffer,
01570     *entry;
01571 
01572   size_t
01573     max_entries;
01574 
01575   /*
01576     Open directory.
01577   */
01578   assert(directory != (const char *) NULL);
01579   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
01580   assert(pattern != (const char *) NULL);
01581   assert(number_entries != (size_t *) NULL);
01582   *number_entries=0;
01583   current_directory=opendir(directory);
01584   if (current_directory == (DIR *) NULL)
01585     return((char **) NULL);
01586   /*
01587     Allocate filelist.
01588   */
01589   max_entries=2048;
01590   filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
01591     sizeof(*filelist));
01592   if (filelist == (char **) NULL)
01593     {
01594       (void) closedir(current_directory);
01595       return((char **) NULL);
01596     }
01597   /*
01598     Save the current and change to the new directory.
01599   */
01600   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
01601     FILENAME_MAX+1);
01602   if (buffer == (struct dirent *) NULL)
01603     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01604   while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
01605          (entry != (struct dirent *) NULL))
01606   {
01607     if (*entry->d_name == '.')
01608       continue;
01609     if ((IsPathDirectory(entry->d_name) > 0) ||
01610 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
01611         (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
01612 #else
01613         (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
01614 #endif
01615       {
01616         if (*number_entries >= max_entries)
01617           {
01618             /*
01619               Extend the file list.
01620             */
01621             max_entries<<=1;
01622             filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
01623               max_entries,sizeof(*filelist));
01624             if (filelist == (char **) NULL)
01625               break;
01626           }
01627 #if defined(vms)
01628         {
01629           register char
01630             *p;
01631 
01632           p=strchr(entry->d_name,';');
01633           if (p)
01634             *p='\0';
01635           if (*number_entries > 0)
01636             if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
01637               continue;
01638         }
01639 #endif
01640         filelist[*number_entries]=(char *) AcquireString(entry->d_name);
01641         (*number_entries)++;
01642       }
01643   }
01644   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
01645   (void) closedir(current_directory);
01646   if (filelist == (char **) NULL)
01647     return((char **) NULL);
01648   /*
01649     Sort filelist in ascending order.
01650   */
01651   qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
01652     FileCompare);
01653   return(filelist);
01654 }
01655 
01656 /*
01657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01658 %                                                                             %
01659 %                                                                             %
01660 %                                                                             %
01661 %   M a g i c k D e l a y                                                     %
01662 %                                                                             %
01663 %                                                                             %
01664 %                                                                             %
01665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01666 %
01667 %  MagickDelay() suspends program execution for the number of milliseconds
01668 %  specified.
01669 %
01670 %  The format of the Delay method is:
01671 %
01672 %      void MagickDelay(const MagickSizeType milliseconds)
01673 %
01674 %  A description of each parameter follows:
01675 %
01676 %    o milliseconds: Specifies the number of milliseconds to delay before
01677 %      returning.
01678 %
01679 */
01680 MagickPrivate void MagickDelay(const MagickSizeType milliseconds)
01681 {
01682   if (milliseconds == 0)
01683     return;
01684 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
01685   {
01686     struct timespec
01687       timer;
01688 
01689     timer.tv_sec=(time_t) (milliseconds/1000);
01690     timer.tv_nsec=(milliseconds % 1000)*1000*1000;
01691     (void) nanosleep(&timer,(struct timespec *) NULL);
01692   }
01693 #elif defined(MAGICKCORE_HAVE_USLEEP)
01694   usleep(1000*milliseconds);
01695 #elif defined(MAGICKCORE_HAVE_SELECT)
01696   {
01697     struct timeval
01698       timer;
01699 
01700     timer.tv_sec=(long) milliseconds/1000;
01701     timer.tv_usec=(long) (milliseconds % 1000)*1000;
01702     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
01703   }
01704 #elif defined(MAGICKCORE_HAVE_POLL)
01705   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
01706 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
01707   Sleep((long) milliseconds);
01708 #elif defined(vms)
01709   {
01710     float
01711       timer;
01712 
01713     timer=milliseconds/1000.0;
01714     lib$wait(&timer);
01715   }
01716 #elif defined(__BEOS__)
01717   snooze(1000*milliseconds);
01718 #else
01719 # error "Time delay method not defined."
01720 #endif
01721 }
01722 
01723 /*
01724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01725 %                                                                             %
01726 %                                                                             %
01727 %                                                                             %
01728 %  M u l t i l i n e C e n s u s                                              %
01729 %                                                                             %
01730 %                                                                             %
01731 %                                                                             %
01732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01733 %
01734 %  MultilineCensus() returns the number of lines within a label.  A line is
01735 %  represented by a \n character.
01736 %
01737 %  The format of the MultilineCenus method is:
01738 %
01739 %      size_t MultilineCensus(const char *label)
01740 %
01741 %  A description of each parameter follows.
01742 %
01743 %   o  label:  This character string is the label.
01744 %
01745 */
01746 MagickExport size_t MultilineCensus(const char *label)
01747 {
01748   size_t
01749     number_lines;
01750 
01751   /*
01752     Determine the number of lines within this label.
01753   */
01754   if (label == (char *) NULL)
01755     return(0);
01756   for (number_lines=1; *label != '\0'; label++)
01757     if (*label == '\n')
01758       number_lines++;
01759   return(number_lines);
01760 }
01761 
01762 /*
01763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01764 %                                                                             %
01765 %                                                                             %
01766 %                                                                             %
01767 %   S y s t e m C o m m a n d                                                 %
01768 %                                                                             %
01769 %                                                                             %
01770 %                                                                             %
01771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01772 %
01773 %  SystemCommand() executes the specified command and waits until it
01774 %  terminates.  The returned value is the exit status of the command.
01775 %
01776 %  The format of the SystemCommand method is:
01777 %
01778 %      int SystemCommand(const MagickBooleanType asynchronous,
01779 %        const MagickBooleanType verbose,const char *command,
01780 %        ExceptionInfo *exception)
01781 %
01782 %  A description of each parameter follows:
01783 %
01784 %    o asynchronous: a value other than 0 executes the parent program
01785 %      concurrently with the new child process.
01786 %
01787 %    o verbose: a value other than 0 prints the executed command before it is
01788 %      invoked.
01789 %
01790 %    o command: this string is the command to execute.
01791 %
01792 %    o exception: return any errors here.
01793 %
01794 */
01795 MagickExport int SystemCommand(const MagickBooleanType asynchronous,
01796   const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
01797 {
01798   char
01799     **arguments,
01800     *shell_command;
01801 
01802   int
01803     number_arguments,
01804     status;
01805 
01806   PolicyDomain
01807     domain;
01808 
01809   PolicyRights
01810     rights;
01811 
01812   register ssize_t
01813     i;
01814 
01815   status=(-1);
01816   arguments=StringToArgv(command,&number_arguments);
01817   if (arguments == (char **) NULL)
01818     return(status);
01819   rights=ExecutePolicyRights;
01820   domain=DelegatePolicyDomain;
01821   if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
01822     {
01823       errno=EPERM;
01824       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
01825         "NotAuthorized","`%s'",arguments[1]);
01826       for (i=0; i < (ssize_t) number_arguments; i++)
01827         arguments[i]=DestroyString(arguments[i]);
01828       arguments=(char **) RelinquishMagickMemory(arguments);
01829       return(-1);
01830     }
01831   if (verbose != MagickFalse)
01832     {
01833       (void) FormatLocaleFile(stderr,"%s\n",command);
01834       (void) fflush(stderr);
01835     }
01836   shell_command=(char *) command;
01837   if (asynchronous != MagickFalse)
01838     {
01839       shell_command=AcquireString(command);
01840       (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
01841     }
01842 #if defined(MAGICKCORE_POSIX_SUPPORT)
01843 #if !defined(MAGICKCORE_HAVE_EXECVP)
01844   status=system(shell_command);
01845 #else
01846   if ((asynchronous != MagickFalse) ||
01847       (strpbrk(shell_command,"&;<>|") != (char *) NULL))
01848     status=system(shell_command);
01849   else
01850     {
01851       pid_t
01852         child_pid;
01853 
01854       /*
01855         Call application directly rather than from a shell.
01856       */
01857       child_pid=fork();
01858       if (child_pid == (pid_t) -1)
01859         status=system(command);
01860       else
01861         if (child_pid == 0)
01862           {
01863             status=execvp(arguments[1],arguments+1);
01864             _exit(1);
01865           }
01866         else
01867           {
01868             int
01869               child_status;
01870 
01871             pid_t
01872               pid;
01873 
01874             child_status=0;
01875             pid=waitpid(child_pid,&child_status,0);
01876             if (pid == -1)
01877               status=(-1);
01878             else
01879               {
01880                 if (WIFEXITED(child_status) != 0)
01881                   status=WEXITSTATUS(child_status);
01882                 else
01883                   if (WIFSIGNALED(child_status))
01884                     status=(-1);
01885               }
01886           }
01887     }
01888 #endif
01889 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
01890   status=NTSystemCommand(shell_command);
01891 #elif defined(macintosh)
01892   status=MACSystemCommand(shell_command);
01893 #elif defined(vms)
01894   status=system(shell_command);
01895 #else
01896 #  error No suitable system() method.
01897 #endif
01898   if (status < 0)
01899     (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
01900       "`%s' (%d)",command,status);
01901   if (shell_command != command)
01902     shell_command=DestroyString(shell_command);
01903   for (i=0; i < (ssize_t) number_arguments; i++)
01904     arguments[i]=DestroyString(arguments[i]);
01905   arguments=(char **) RelinquishMagickMemory(arguments);
01906   return(status);
01907 }