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