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