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