utility.c revision e5b39652d8d21bc3940d83b8d6088d4070a8a34a
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-2012 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,"PANGO") == 0) || 772 (LocaleCompare(magick,"VID") == 0)) 773 continue; 774 if ((IsGlob(filename) == MagickFalse) && (*filename != '@')) 775 continue; 776 if (*filename != '@') 777 { 778 /* 779 Generate file list from wildcard filename (e.g. *.jpg). 780 */ 781 GetPathComponent(option,HeadPath,path); 782 GetPathComponent(option,SubimagePath,subimage); 783 ExpandFilename(path); 784 if (*home_directory == '\0') 785 directory=getcwd(home_directory,MaxTextExtent-1); 786 (void) directory; 787 filelist=ListFiles(*path == '\0' ? home_directory : path,filename, 788 &number_files); 789 } 790 else 791 { 792 char 793 *files; 794 795 ExceptionInfo 796 *exception; 797 798 int 799 length; 800 801 /* 802 Generate file list from file list (e.g. @filelist.txt). 803 */ 804 exception=AcquireExceptionInfo(); 805 files=FileToString(filename+1,~0,exception); 806 exception=DestroyExceptionInfo(exception); 807 if (files == (char *) NULL) 808 continue; 809 filelist=StringToArgv(files,&length); 810 if (filelist == (char **) NULL) 811 continue; 812 files=DestroyString(files); 813 filelist[0]=DestroyString(filelist[0]); 814 for (j=0; j < (ssize_t) (length-1); j++) 815 filelist[j]=filelist[j+1]; 816 number_files=(size_t) length-1; 817 } 818 if (filelist == (char **) NULL) 819 continue; 820 for (j=0; j < (ssize_t) number_files; j++) 821 if (IsPathDirectory(filelist[j]) <= 0) 822 break; 823 if (j == (ssize_t) number_files) 824 { 825 for (j=0; j < (ssize_t) number_files; j++) 826 filelist[j]=DestroyString(filelist[j]); 827 filelist=(char **) RelinquishMagickMemory(filelist); 828 continue; 829 } 830 /* 831 Transfer file list to argument vector. 832 */ 833 vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+ 834 count+number_files+1,sizeof(*vector)); 835 if (vector == (char **) NULL) 836 return(MagickFalse); 837 for (j=0; j < (ssize_t) number_files; j++) 838 { 839 option=filelist[j]; 840 parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option); 841 if (parameters > 0) 842 { 843 ssize_t 844 k; 845 846 /* 847 Do not expand command option parameters. 848 */ 849 vector[count++]=ConstantString(option); 850 for (k=0; k < parameters; k++) 851 { 852 j++; 853 if (j == (ssize_t) number_files) 854 break; 855 option=filelist[j]; 856 vector[count++]=ConstantString(option); 857 } 858 continue; 859 } 860 (void) CopyMagickString(filename,path,MaxTextExtent); 861 if (*path != '\0') 862 (void) ConcatenateMagickString(filename,DirectorySeparator, 863 MaxTextExtent); 864 (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent); 865 filelist[j]=DestroyString(filelist[j]); 866 if (strlen(filename) >= (MaxTextExtent-1)) 867 ThrowFatalException(OptionFatalError,"FilenameTruncated"); 868 if (IsPathDirectory(filename) <= 0) 869 { 870 char 871 path[MaxTextExtent]; 872 873 *path='\0'; 874 if (*magick != '\0') 875 { 876 (void) ConcatenateMagickString(path,magick,MaxTextExtent); 877 (void) ConcatenateMagickString(path,":",MaxTextExtent); 878 } 879 (void) ConcatenateMagickString(path,filename,MaxTextExtent); 880 if (*subimage != '\0') 881 { 882 (void) ConcatenateMagickString(path,"[",MaxTextExtent); 883 (void) ConcatenateMagickString(path,subimage,MaxTextExtent); 884 (void) ConcatenateMagickString(path,"]",MaxTextExtent); 885 } 886 if (strlen(path) >= (MaxTextExtent-1)) 887 ThrowFatalException(OptionFatalError,"FilenameTruncated"); 888 if (destroy != MagickFalse) 889 { 890 count--; 891 vector[count]=DestroyString(vector[count]); 892 destroy=MagickFalse; 893 } 894 vector[count++]=ConstantString(path); 895 } 896 } 897 filelist=(char **) RelinquishMagickMemory(filelist); 898 } 899 vector[count]=(char *) NULL; 900 if (IsEventLogging() != MagickFalse) 901 { 902 char 903 *command_line; 904 905 command_line=AcquireString(vector[0]); 906 for (i=1; i < count; i++) 907 { 908 (void) ConcatenateString(&command_line," {"); 909 (void) ConcatenateString(&command_line,vector[i]); 910 (void) ConcatenateString(&command_line,"}"); 911 } 912 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), 913 "Command line: %s",command_line); 914 command_line=DestroyString(command_line); 915 } 916 *number_arguments=(int) count; 917 *arguments=vector; 918 return(MagickTrue); 919} 920 921/* 922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 923% % 924% % 925% % 926% G e t E x e c u t i o n P a t h % 927% % 928% % 929% % 930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 931% 932% GetExecutionPath() returns the pathname of the executable that started 933% the process. On success MagickTrue is returned, otherwise MagickFalse. 934% 935% The format of the GetExecutionPath method is: 936% 937% MagickBooleanType GetExecutionPath(char *path,const size_t extent) 938% 939% A description of each parameter follows: 940% 941% o path: the pathname of the executable that started the process. 942% 943% o extent: the maximum extent of the path. 944% 945*/ 946MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent) 947{ 948 char 949 *directory; 950 951 *path='\0'; 952 directory=getcwd(path,(unsigned long) extent); 953 (void) directory; 954#if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX) 955 { 956 char 957 link_path[MaxTextExtent], 958 execution_path[PATH_MAX+1]; 959 960 ssize_t 961 count; 962 963 (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe", 964 (double) getpid()); 965 count=readlink(link_path,execution_path,PATH_MAX); 966 if (count == -1) 967 { 968 (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file", 969 (double) getpid()); 970 count=readlink(link_path,execution_path,PATH_MAX); 971 } 972 if ((count > 0) && (count <= (ssize_t) PATH_MAX)) 973 { 974 execution_path[count]='\0'; 975 (void) CopyMagickString(path,execution_path,extent); 976 } 977 } 978#endif 979#if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH) 980 { 981 char 982 executable_path[PATH_MAX << 1], 983 execution_path[PATH_MAX+1]; 984 985 uint32_t 986 length; 987 988 length=sizeof(executable_path); 989 if ((_NSGetExecutablePath(executable_path,&length) == 0) && 990 (realpath(executable_path,execution_path) != (char *) NULL)) 991 (void) CopyMagickString(path,execution_path,extent); 992 } 993#endif 994#if defined(MAGICKCORE_HAVE_GETEXECNAME) 995 { 996 const char 997 *execution_path; 998 999 execution_path=(const char *) getexecname(); 1000 if (execution_path != (const char *) NULL) 1001 { 1002 if (*execution_path != *DirectorySeparator) 1003 (void) ConcatenateMagickString(path,DirectorySeparator,extent); 1004 (void) ConcatenateMagickString(path,execution_path,extent); 1005 } 1006 } 1007#endif 1008#if defined(MAGICKCORE_WINDOWS_SUPPORT) 1009 NTGetExecutionPath(path,extent); 1010#endif 1011#if defined(__GNU__) 1012 { 1013 char 1014 *program_name, 1015 *execution_path; 1016 1017 ssize_t 1018 count; 1019 1020 count=0; 1021 execution_path=(char *) NULL; 1022 program_name=program_invocation_name; 1023 if (*program_invocation_name != '/') 1024 { 1025 size_t 1026 extent; 1027 1028 extent=strlen(directory)+strlen(program_name)+2; 1029 program_name=AcquireQuantumMemory(extent,sizeof(*program_name)); 1030 if (program_name == (char *) NULL) 1031 program_name=program_invocation_name; 1032 else 1033 count=FormatLocaleString(program_name,extent,"%s/%s",directory, 1034 program_invocation_name); 1035 } 1036 if (count != -1) 1037 { 1038 execution_path=realpath(program_name,NULL); 1039 if (execution_path != (char *) NULL) 1040 (void) CopyMagickString(path,execution_path,extent); 1041 } 1042 if (program_name != program_invocation_name) 1043 program_name=(char *) RelinquishMagickMemory(program_name); 1044 execution_path=(char *) RelinquishMagickMemory(execution_path); 1045 } 1046#endif 1047 return(IsPathAccessible(path)); 1048} 1049 1050/* 1051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1052% % 1053% % 1054% % 1055% G e t M a g i c k P a g e S i z e % 1056% % 1057% % 1058% % 1059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1060% 1061% GetMagickPageSize() returns the memory page size. 1062% 1063% The format of the GetMagickPageSize method is: 1064% 1065% ssize_t GetMagickPageSize() 1066% 1067*/ 1068MagickPrivate ssize_t GetMagickPageSize(void) 1069{ 1070 static ssize_t 1071 page_size = -1; 1072 1073 if (page_size > 0) 1074 return(page_size); 1075#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) 1076 page_size=(ssize_t) sysconf(_SC_PAGE_SIZE); 1077#else 1078#if defined(MAGICKCORE_HAVE_GETPAGESIZE) 1079 page_size=(ssize_t) getpagesize(); 1080#endif 1081#endif 1082 if (page_size <= 0) 1083 page_size=16384; 1084 return(page_size); 1085} 1086 1087/* 1088%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1089% % 1090% % 1091% % 1092% G e t P a t h A t t r i b u t e s % 1093% % 1094% % 1095% % 1096%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1097% 1098% GetPathAttributes() returns attributes (e.g. size of file) about a path. 1099% 1100% The path of the GetPathAttributes method is: 1101% 1102% MagickBooleanType GetPathAttributes(const char *path,void *attributes) 1103% 1104% A description of each parameter follows. 1105% 1106% o path: the file path. 1107% 1108% o attributes: the path attributes are returned here. 1109% 1110*/ 1111MagickExport MagickBooleanType GetPathAttributes(const char *path, 1112 void *attributes) 1113{ 1114 MagickBooleanType 1115 status; 1116 1117 if (path == (const char *) NULL) 1118 { 1119 errno=EINVAL; 1120 return(MagickFalse); 1121 } 1122 status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue : 1123 MagickFalse; 1124 return(status); 1125} 1126 1127/* 1128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1129% % 1130% % 1131% % 1132% G e t P a t h C o m p o n e n t % 1133% % 1134% % 1135% % 1136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1137% 1138% GetPathComponent() returns the parent directory name, filename, basename, or 1139% extension of a file path. 1140% 1141% The format of the GetPathComponent function is: 1142% 1143% GetPathComponent(const char *path,PathType type,char *component) 1144% 1145% A description of each parameter follows: 1146% 1147% o path: Specifies a pointer to a character array that contains the 1148% file path. 1149% 1150% o type: Specififies which file path component to return. 1151% 1152% o component: the selected file path component is returned here. 1153% 1154*/ 1155MagickExport void GetPathComponent(const char *path,PathType type, 1156 char *component) 1157{ 1158 char 1159 magick[MaxTextExtent], 1160 *q, 1161 subimage[MaxTextExtent]; 1162 1163 register char 1164 *p; 1165 1166 assert(path != (const char *) NULL); 1167 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path); 1168 assert(component != (char *) NULL); 1169 if (*path == '\0') 1170 { 1171 *component='\0'; 1172 return; 1173 } 1174 (void) CopyMagickString(component,path,MaxTextExtent); 1175 *magick='\0'; 1176#if defined(__OS2__) 1177 if (path[1] != ":") 1178#endif 1179 for (p=component; *p != '\0'; p++) 1180 { 1181 if ((*p == '%') && (*(p+1) == '[')) 1182 { 1183 /* 1184 Skip over %[...]. 1185 */ 1186 for (p++; (*p != ']') && (*p != '\0'); p++) ; 1187 if (*p == '\0') 1188 break; 1189 } 1190 if ((*p == ':') && (IsPathDirectory(path) < 0) && 1191 (IsPathAccessible(path) == MagickFalse)) 1192 { 1193 /* 1194 Look for image format specification (e.g. ps3:image). 1195 */ 1196 (void) CopyMagickString(magick,component,(size_t) (p-component+1)); 1197 if (IsMagickConflict(magick) != MagickFalse) 1198 *magick='\0'; 1199 else 1200 for (q=component; *q != '\0'; q++) 1201 *q=(*++p); 1202 break; 1203 } 1204 } 1205 *subimage='\0'; 1206 p=component; 1207 if (*p != '\0') 1208 p=component+strlen(component)-1; 1209 if ((*p == ']') && (strchr(component,'[') != (char *) NULL) && 1210 (IsPathAccessible(path) == MagickFalse)) 1211 { 1212 /* 1213 Look for scene specification (e.g. img0001.pcd[4]). 1214 */ 1215 for (q=p-1; q > component; q--) 1216 if (*q == '[') 1217 break; 1218 if (*q == '[') 1219 { 1220 (void) CopyMagickString(subimage,q+1,MaxTextExtent); 1221 subimage[p-q-1]='\0'; 1222 if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) && 1223 (IsGeometry(subimage) == MagickFalse)) 1224 *subimage='\0'; 1225 else 1226 *q='\0'; 1227 } 1228 } 1229 p=component; 1230 if (*p != '\0') 1231 for (p=component+strlen(component)-1; p > component; p--) 1232 if (IsBasenameSeparator(*p) != MagickFalse) 1233 break; 1234 switch (type) 1235 { 1236 case MagickPath: 1237 { 1238 (void) CopyMagickString(component,magick,MaxTextExtent); 1239 break; 1240 } 1241 case RootPath: 1242 { 1243 for (p=component+(strlen(component)-1); p > component; p--) 1244 { 1245 if (IsBasenameSeparator(*p) != MagickFalse) 1246 break; 1247 if (*p == '.') 1248 break; 1249 } 1250 if (*p == '.') 1251 *p='\0'; 1252 break; 1253 } 1254 case HeadPath: 1255 { 1256 *p='\0'; 1257 break; 1258 } 1259 case TailPath: 1260 { 1261 if (IsBasenameSeparator(*p) != MagickFalse) 1262 (void) CopyMagickMemory((unsigned char *) component, 1263 (const unsigned char *) (p+1),strlen(p+1)+1); 1264 break; 1265 } 1266 case BasePath: 1267 { 1268 if (IsBasenameSeparator(*p) != MagickFalse) 1269 (void) CopyMagickString(component,p+1,MaxTextExtent); 1270 for (p=component+(strlen(component)-1); p > component; p--) 1271 if (*p == '.') 1272 { 1273 *p='\0'; 1274 break; 1275 } 1276 break; 1277 } 1278 case ExtensionPath: 1279 { 1280 if (IsBasenameSeparator(*p) != MagickFalse) 1281 (void) CopyMagickString(component,p+1,MaxTextExtent); 1282 p=component; 1283 if (*p != '\0') 1284 for (p=component+strlen(component)-1; p > component; p--) 1285 if (*p == '.') 1286 break; 1287 *component='\0'; 1288 if (*p == '.') 1289 (void) CopyMagickString(component,p+1,MaxTextExtent); 1290 break; 1291 } 1292 case SubimagePath: 1293 { 1294 (void) CopyMagickString(component,subimage,MaxTextExtent); 1295 break; 1296 } 1297 case CanonicalPath: 1298 case UndefinedPath: 1299 break; 1300 } 1301} 1302 1303/* 1304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1305% % 1306% % 1307% % 1308% G e t P a t h C o m p o n e n t s % 1309% % 1310% % 1311% % 1312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1313% 1314% GetPathComponents() returns a list of path components. 1315% 1316% The format of the GetPathComponents method is: 1317% 1318% char **GetPathComponents(const char *path, 1319% size_t *number_componenets) 1320% 1321% A description of each parameter follows: 1322% 1323% o path: Specifies the string to segment into a list. 1324% 1325% o number_components: return the number of components in the list 1326% 1327*/ 1328MagickPrivate char **GetPathComponents(const char *path, 1329 size_t *number_components) 1330{ 1331 char 1332 **components; 1333 1334 register const char 1335 *p, 1336 *q; 1337 1338 register ssize_t 1339 i; 1340 1341 if (path == (char *) NULL) 1342 return((char **) NULL); 1343 *number_components=1; 1344 for (p=path; *p != '\0'; p++) 1345 if (IsBasenameSeparator(*p)) 1346 (*number_components)++; 1347 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL, 1348 sizeof(*components)); 1349 if (components == (char **) NULL) 1350 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 1351 p=path; 1352 for (i=0; i < (ssize_t) *number_components; i++) 1353 { 1354 for (q=p; *q != '\0'; q++) 1355 if (IsBasenameSeparator(*q)) 1356 break; 1357 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent, 1358 sizeof(**components)); 1359 if (components[i] == (char *) NULL) 1360 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 1361 (void) CopyMagickString(components[i],p,(size_t) (q-p+1)); 1362 p=q+1; 1363 } 1364 components[i]=(char *) NULL; 1365 return(components); 1366} 1367 1368/* 1369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1370% % 1371% % 1372% % 1373% I s P a t h A c c e s s i b l e % 1374% % 1375% % 1376% % 1377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1378% 1379% IsPathAccessible() returns MagickTrue if the file as defined by the path is 1380% accessible. 1381% 1382% The format of the IsPathAccessible method is: 1383% 1384% MagickBooleanType IsPathAccessible(const char *filename) 1385% 1386% A description of each parameter follows. 1387% 1388% o path: Specifies a path to a file. 1389% 1390*/ 1391MagickExport MagickBooleanType IsPathAccessible(const char *path) 1392{ 1393 MagickBooleanType 1394 status; 1395 1396 struct stat 1397 attributes; 1398 1399 if ((path == (const char *) NULL) || (*path == '\0')) 1400 return(MagickFalse); 1401 status=GetPathAttributes(path,&attributes); 1402 if (status == MagickFalse) 1403 return(status); 1404 if (S_ISREG(attributes.st_mode) == 0) 1405 return(MagickFalse); 1406 if (access_utf8(path,F_OK) != 0) 1407 return(MagickFalse); 1408 return(MagickTrue); 1409} 1410 1411/* 1412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1413% % 1414% % 1415% % 1416+ I s P a t h D i r e c t o r y % 1417% % 1418% % 1419% % 1420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1421% 1422% IsPathDirectory() returns -1 if the directory does not exist, 1 is returned 1423% if the path represents a directory otherwise 0. 1424% 1425% The format of the IsPathDirectory method is: 1426% 1427% int IsPathDirectory(const char *path) 1428% 1429% A description of each parameter follows. 1430% 1431% o path: The directory path. 1432% 1433*/ 1434static int IsPathDirectory(const char *path) 1435{ 1436 MagickBooleanType 1437 status; 1438 1439 struct stat 1440 attributes; 1441 1442 if ((path == (const char *) NULL) || (*path == '\0')) 1443 return(MagickFalse); 1444 status=GetPathAttributes(path,&attributes); 1445 if (status == MagickFalse) 1446 return(-1); 1447 if (S_ISDIR(attributes.st_mode) == 0) 1448 return(0); 1449 return(1); 1450} 1451 1452/* 1453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1454% % 1455% % 1456% % 1457% L i s t F i l e s % 1458% % 1459% % 1460% % 1461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1462% 1463% ListFiles() reads the directory specified and returns a list of filenames 1464% contained in the directory sorted in ascending alphabetic order. 1465% 1466% The format of the ListFiles function is: 1467% 1468% char **ListFiles(const char *directory,const char *pattern, 1469% ssize_t *number_entries) 1470% 1471% A description of each parameter follows: 1472% 1473% o filelist: Method ListFiles returns a list of filenames contained 1474% in the directory. If the directory specified cannot be read or it is 1475% a file a NULL list is returned. 1476% 1477% o directory: Specifies a pointer to a text string containing a directory 1478% name. 1479% 1480% o pattern: Specifies a pointer to a text string containing a pattern. 1481% 1482% o number_entries: This integer returns the number of filenames in the 1483% list. 1484% 1485*/ 1486 1487#if defined(__cplusplus) || defined(c_plusplus) 1488extern "C" { 1489#endif 1490 1491static int FileCompare(const void *x,const void *y) 1492{ 1493 register const char 1494 **p, 1495 **q; 1496 1497 p=(const char **) x; 1498 q=(const char **) y; 1499 return(LocaleCompare(*p,*q)); 1500} 1501 1502#if defined(__cplusplus) || defined(c_plusplus) 1503} 1504#endif 1505 1506static inline int MagickReadDirectory(DIR *directory,struct dirent *entry, 1507 struct dirent **result) 1508{ 1509#if defined(MAGICKCORE_HAVE_READDIR_R) 1510 return(readdir_r(directory,entry,result)); 1511#else 1512 (void) entry; 1513 errno=0; 1514 *result=readdir(directory); 1515 return(errno); 1516#endif 1517} 1518 1519MagickPrivate char **ListFiles(const char *directory,const char *pattern, 1520 size_t *number_entries) 1521{ 1522 char 1523 **filelist; 1524 1525 DIR 1526 *current_directory; 1527 1528 struct dirent 1529 *buffer, 1530 *entry; 1531 1532 size_t 1533 max_entries; 1534 1535 /* 1536 Open directory. 1537 */ 1538 assert(directory != (const char *) NULL); 1539 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory); 1540 assert(pattern != (const char *) NULL); 1541 assert(number_entries != (size_t *) NULL); 1542 *number_entries=0; 1543 current_directory=opendir(directory); 1544 if (current_directory == (DIR *) NULL) 1545 return((char **) NULL); 1546 /* 1547 Allocate filelist. 1548 */ 1549 max_entries=2048; 1550 filelist=(char **) AcquireQuantumMemory((size_t) max_entries, 1551 sizeof(*filelist)); 1552 if (filelist == (char **) NULL) 1553 { 1554 (void) closedir(current_directory); 1555 return((char **) NULL); 1556 } 1557 /* 1558 Save the current and change to the new directory. 1559 */ 1560 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+ 1561 FILENAME_MAX+1); 1562 if (buffer == (struct dirent *) NULL) 1563 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 1564 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) && 1565 (entry != (struct dirent *) NULL)) 1566 { 1567 if (*entry->d_name == '.') 1568 continue; 1569 if ((IsPathDirectory(entry->d_name) > 0) || 1570#if defined(MAGICKCORE_WINDOWS_SUPPORT) 1571 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse)) 1572#else 1573 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse)) 1574#endif 1575 { 1576 if (*number_entries >= max_entries) 1577 { 1578 /* 1579 Extend the file list. 1580 */ 1581 max_entries<<=1; 1582 filelist=(char **) ResizeQuantumMemory(filelist,(size_t) 1583 max_entries,sizeof(*filelist)); 1584 if (filelist == (char **) NULL) 1585 break; 1586 } 1587#if defined(vms) 1588 { 1589 register char 1590 *p; 1591 1592 p=strchr(entry->d_name,';'); 1593 if (p) 1594 *p='\0'; 1595 if (*number_entries > 0) 1596 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0) 1597 continue; 1598 } 1599#endif 1600 filelist[*number_entries]=(char *) AcquireString(entry->d_name); 1601 (*number_entries)++; 1602 } 1603 } 1604 buffer=(struct dirent *) RelinquishMagickMemory(buffer); 1605 (void) closedir(current_directory); 1606 if (filelist == (char **) NULL) 1607 return((char **) NULL); 1608 /* 1609 Sort filelist in ascending order. 1610 */ 1611 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist), 1612 FileCompare); 1613 return(filelist); 1614} 1615 1616/* 1617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1618% % 1619% % 1620% % 1621% M a g i c k D e l a y % 1622% % 1623% % 1624% % 1625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1626% 1627% MagickDelay() suspends program execution for the number of milliseconds 1628% specified. 1629% 1630% The format of the Delay method is: 1631% 1632% void MagickDelay(const MagickSizeType milliseconds) 1633% 1634% A description of each parameter follows: 1635% 1636% o milliseconds: Specifies the number of milliseconds to delay before 1637% returning. 1638% 1639*/ 1640MagickPrivate void MagickDelay(const MagickSizeType milliseconds) 1641{ 1642 if (milliseconds == 0) 1643 return; 1644#if defined(MAGICKCORE_HAVE_NANOSLEEP) 1645 { 1646 struct timespec 1647 timer; 1648 1649 timer.tv_sec=(time_t) (milliseconds/1000); 1650 timer.tv_nsec=(milliseconds % 1000)*1000*1000; 1651 (void) nanosleep(&timer,(struct timespec *) NULL); 1652 } 1653#elif defined(MAGICKCORE_HAVE_USLEEP) 1654 usleep(1000*milliseconds); 1655#elif defined(MAGICKCORE_HAVE_SELECT) 1656 { 1657 struct timeval 1658 timer; 1659 1660 timer.tv_sec=(long) milliseconds/1000; 1661 timer.tv_usec=(long) (milliseconds % 1000)*1000; 1662 (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer); 1663 } 1664#elif defined(MAGICKCORE_HAVE_POLL) 1665 (void) poll((struct pollfd *) NULL,0,(int) milliseconds); 1666#elif defined(MAGICKCORE_WINDOWS_SUPPORT) 1667 Sleep((long) milliseconds); 1668#elif defined(vms) 1669 { 1670 float 1671 timer; 1672 1673 timer=milliseconds/1000.0; 1674 lib$wait(&timer); 1675 } 1676#elif defined(__BEOS__) 1677 snooze(1000*milliseconds); 1678#else 1679# error "Time delay method not defined." 1680#endif 1681} 1682 1683/* 1684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1685% % 1686% % 1687% % 1688% M u l t i l i n e C e n s u s % 1689% % 1690% % 1691% % 1692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1693% 1694% MultilineCensus() returns the number of lines within a label. A line is 1695% represented by a \n character. 1696% 1697% The format of the MultilineCenus method is: 1698% 1699% size_t MultilineCensus(const char *label) 1700% 1701% A description of each parameter follows. 1702% 1703% o label: This character string is the label. 1704% 1705*/ 1706MagickExport size_t MultilineCensus(const char *label) 1707{ 1708 size_t 1709 number_lines; 1710 1711 /* 1712 Determine the number of lines within this label. 1713 */ 1714 if (label == (char *) NULL) 1715 return(0); 1716 for (number_lines=1; *label != '\0'; label++) 1717 if (*label == '\n') 1718 number_lines++; 1719 return(number_lines); 1720} 1721 1722/* 1723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1724% % 1725% % 1726% % 1727% S y s t e m C o m m a n d % 1728% % 1729% % 1730% % 1731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1732% 1733% SystemCommand() executes the specified command and waits until it 1734% terminates. The returned value is the exit status of the command. 1735% 1736% The format of the SystemCommand method is: 1737% 1738% int SystemCommand(const MagickBooleanType asynchronous, 1739% const MagickBooleanType verbose,const char *command, 1740% ExceptionInfo *exception) 1741% 1742% A description of each parameter follows: 1743% 1744% o asynchronous: a value other than 0 executes the parent program 1745% concurrently with the new child process. 1746% 1747% o verbose: a value other than 0 prints the executed command before it is 1748% invoked. 1749% 1750% o command: this string is the command to execute. 1751% 1752% o exception: return any errors here. 1753% 1754*/ 1755MagickExport int SystemCommand(const MagickBooleanType asynchronous, 1756 const MagickBooleanType verbose,const char *command,ExceptionInfo *exception) 1757{ 1758 char 1759 **arguments, 1760 *shell_command; 1761 1762 int 1763 number_arguments, 1764 status; 1765 1766 PolicyDomain 1767 domain; 1768 1769 PolicyRights 1770 rights; 1771 1772 register ssize_t 1773 i; 1774 1775 status=(-1); 1776 arguments=StringToArgv(command,&number_arguments); 1777 if (arguments == (char **) NULL) 1778 return(status); 1779 rights=ExecutePolicyRights; 1780 domain=DelegatePolicyDomain; 1781 if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse) 1782 { 1783 errno=EPERM; 1784 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, 1785 "NotAuthorized","'%s'",arguments[1]); 1786 for (i=0; i < (ssize_t) number_arguments; i++) 1787 arguments[i]=DestroyString(arguments[i]); 1788 arguments=(char **) RelinquishMagickMemory(arguments); 1789 return(-1); 1790 } 1791 if (verbose != MagickFalse) 1792 { 1793 (void) FormatLocaleFile(stderr,"%s\n",command); 1794 (void) fflush(stderr); 1795 } 1796 shell_command=(char *) command; 1797 if (asynchronous != MagickFalse) 1798 { 1799 shell_command=AcquireString(command); 1800 (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent); 1801 } 1802#if defined(MAGICKCORE_POSIX_SUPPORT) 1803#if !defined(MAGICKCORE_HAVE_EXECVP) 1804 status=system(shell_command); 1805#else 1806 if ((asynchronous != MagickFalse) || 1807 (strpbrk(shell_command,"&;<>|") != (char *) NULL)) 1808 status=system(shell_command); 1809 else 1810 { 1811 pid_t 1812 child_pid; 1813 1814 /* 1815 Call application directly rather than from a shell. 1816 */ 1817 child_pid=(pid_t) fork(); 1818 if (child_pid == (pid_t) -1) 1819 status=system(command); 1820 else 1821 if (child_pid == 0) 1822 { 1823 status=execvp(arguments[1],arguments+1); 1824 _exit(1); 1825 } 1826 else 1827 { 1828 int 1829 child_status; 1830 1831 pid_t 1832 pid; 1833 1834 child_status=0; 1835 pid=(pid_t) waitpid(child_pid,&child_status,0); 1836 if (pid == -1) 1837 status=(-1); 1838 else 1839 { 1840 if (WIFEXITED(child_status) != 0) 1841 status=WEXITSTATUS(child_status); 1842 else 1843 if (WIFSIGNALED(child_status)) 1844 status=(-1); 1845 } 1846 } 1847 } 1848#endif 1849#elif defined(MAGICKCORE_WINDOWS_SUPPORT) 1850 status=NTSystemCommand(shell_command); 1851#elif defined(macintosh) 1852 status=MACSystemCommand(shell_command); 1853#elif defined(vms) 1854 status=system(shell_command); 1855#else 1856# error No suitable system() method. 1857#endif 1858 if (status < 0) 1859 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError, 1860 "'%s' (%d)",command,status); 1861 if (shell_command != command) 1862 shell_command=DestroyString(shell_command); 1863 for (i=0; i < (ssize_t) number_arguments; i++) 1864 arguments[i]=DestroyString(arguments[i]); 1865 arguments=(char **) RelinquishMagickMemory(arguments); 1866 return(status); 1867} 1868