blob: 196f94f651b593510ee3bed323e14d55c0a1434c [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);
cristyfa09d142009-10-15 01:02:25 +0000908#if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
cristy3ed852e2009-09-05 21:47:34 +0000909 {
910 char
911 link_path[MaxTextExtent],
cristyfa09d142009-10-15 01:02:25 +0000912 execution_path[PATH_MAX+1];
cristy3ed852e2009-09-05 21:47:34 +0000913
914 ssize_t
915 count;
916
917 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/exe",
918 (long) getpid());
cristyfa09d142009-10-15 01:02:25 +0000919 count=readlink(link_path,execution_path,PATH_MAX);
cristy3ed852e2009-09-05 21:47:34 +0000920 if (count == -1)
921 {
922 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/file",
923 (long) getpid());
cristyfa09d142009-10-15 01:02:25 +0000924 count=readlink(link_path,execution_path,PATH_MAX);
cristy3ed852e2009-09-05 21:47:34 +0000925 }
926 if ((count > 0) && (count <= (ssize_t) PATH_MAX))
927 {
cristyfa09d142009-10-15 01:02:25 +0000928 execution_path[count]='\0';
929 (void) CopyMagickString(path,execution_path,extent);
cristy3ed852e2009-09-05 21:47:34 +0000930 }
931 }
932#endif
933#if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
934 {
935 char
936 executable_path[PATH_MAX << 1],
cristyfa09d142009-10-15 01:02:25 +0000937 execution_path[PATH_MAX+1];
cristy3ed852e2009-09-05 21:47:34 +0000938
939 uint32_t
940 length;
941
942 length=sizeof(executable_path);
943 if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
cristyfa09d142009-10-15 01:02:25 +0000944 (realpath(executable_path,execution_path) != (char *) NULL))
945 (void) CopyMagickString(path,execution_path,extent);
cristy3ed852e2009-09-05 21:47:34 +0000946 }
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
cristyfa09d142009-10-15 01:02:25 +0000965#if defined(__GNU__)
966 {
967 char
968 *program_name,
969 *execution_path;
970
971 long
972 count;
973
974 count=0;
975 execution_path=(char *) NULL;
976 program_name=program_invocation_name;
977 if (*program_invocation_name != '/')
978 {
979 size_t
980 extent;
981
982 extent=strlen(cwd)+strlen(program_name)+1;
983 program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
984 if (program_name == (char *) NULL)
985 program_name=program_invocation_name;
986 else
987 count=FormatMagickString(program_name,extent,"%s/%s",cwd,
988 program_invocation_name);
989 }
990 if (count != -1)
991 {
992 execution_path=realpath(program_name,NULL);
993 if (execution_path != (char *) NULL)
994 (void) CopyMagickString(path,execution_path,extent);
995 }
996 if (program_name != program_invocation_name)
997 program_name=(char *) RelinquishMagickMemory(program_name);
998 execution_path=(char *) RelinquishMagickMemory(execution_path);
999 }
1000#endif
cristy3ed852e2009-09-05 21:47:34 +00001001 return(IsPathAccessible(path));
1002}
1003
1004/*
1005%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1006% %
1007% %
1008% %
cristy688f07b2009-09-27 15:19:13 +00001009% G e t M a g i c k P a g e S i z e %
1010% %
1011% %
1012% %
1013%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1014%
1015% GetMagickPageSize() returns the memory page size.
1016%
1017% The format of the GetMagickPageSize method is:
1018%
1019% long GetMagickPageSize()
1020%
1021*/
1022MagickExport long GetMagickPageSize(void)
1023{
1024 static long
1025 page_size = -1;
1026
1027 if (page_size > 0)
1028 return(page_size);
1029#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1030 page_size=sysconf(_SC_PAGE_SIZE);
1031#endif
1032#if defined(MAGICKCORE_HAVE_GETPAGESIZE)
1033 if (page_size <= 0)
1034 page_size=getpagesize();
1035#endif
1036 if (page_size <= 0)
1037 page_size=16384;
1038 return(page_size);
1039}
1040
1041/*
1042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043% %
1044% %
1045% %
cristy3ed852e2009-09-05 21:47:34 +00001046% G e t P a t h A t t r i b u t e s %
1047% %
1048% %
1049% %
1050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1051%
1052% GetPathAttributes() returns attributes (e.g. size of file) about a path.
1053%
1054% The path of the GetPathAttributes method is:
1055%
1056% MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1057%
1058% A description of each parameter follows.
1059%
1060% o path: the file path.
1061%
1062% o attributes: the path attributes are returned here.
1063%
1064*/
1065
1066#if defined(MAGICKCORE_HAVE__WFOPEN)
1067static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
1068{
1069 register const unsigned char
1070 *p;
1071
1072 if (utf16 != (wchar_t *) NULL)
1073 {
1074 register wchar_t
1075 *q;
1076
1077 wchar_t
1078 c;
1079
1080 /*
1081 Convert UTF-8 to UTF-16.
1082 */
1083 q=utf16;
1084 for (p=utf8; *p != '\0'; p++)
1085 {
1086 if ((*p & 0x80) == 0)
1087 *q=(*p);
1088 else
1089 if ((*p & 0xE0) == 0xC0)
1090 {
1091 c=(*p);
1092 *q=(c & 0x1F) << 6;
1093 p++;
1094 if ((*p & 0xC0) != 0x80)
1095 return(0);
1096 *q|=(*p & 0x3F);
1097 }
1098 else
1099 if ((*p & 0xF0) == 0xE0)
1100 {
1101 c=(*p);
1102 *q=c << 12;
1103 p++;
1104 if ((*p & 0xC0) != 0x80)
1105 return(0);
1106 c=(*p);
1107 *q|=(c & 0x3F) << 6;
1108 p++;
1109 if ((*p & 0xC0) != 0x80)
1110 return(0);
1111 *q|=(*p & 0x3F);
1112 }
1113 else
1114 return(0);
1115 q++;
1116 }
1117 *q++='\0';
1118 return(q-utf16);
1119 }
1120 /*
1121 Compute UTF-16 string length.
1122 */
1123 for (p=utf8; *p != '\0'; p++)
1124 {
1125 if ((*p & 0x80) == 0)
1126 ;
1127 else
1128 if ((*p & 0xE0) == 0xC0)
1129 {
1130 p++;
1131 if ((*p & 0xC0) != 0x80)
1132 return(0);
1133 }
1134 else
1135 if ((*p & 0xF0) == 0xE0)
1136 {
1137 p++;
1138 if ((*p & 0xC0) != 0x80)
1139 return(0);
1140 p++;
1141 if ((*p & 0xC0) != 0x80)
1142 return(0);
1143 }
1144 else
1145 return(0);
1146 }
1147 return(p-utf8);
1148}
1149
1150static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
1151{
1152 size_t
1153 length;
1154
1155 wchar_t
1156 *utf16;
1157
1158 length=UTF8ToUTF16(source,(wchar_t *) NULL);
1159 if (length == 0)
1160 {
1161 register long
1162 i;
1163
1164 /*
1165 Not UTF-8, just copy.
1166 */
1167 length=strlen(source);
1168 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
1169 if (utf16 == (wchar_t *) NULL)
1170 return((wchar_t *) NULL);
1171 for (i=0; i <= (long) length; i++)
1172 utf16[i]=source[i];
1173 return(utf16);
1174 }
1175 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
1176 if (utf16 == (wchar_t *) NULL)
1177 return((wchar_t *) NULL);
1178 length=UTF8ToUTF16(source,utf16);
1179 return(utf16);
1180}
1181#endif
1182
1183MagickExport MagickBooleanType GetPathAttributes(const char *path,
1184 void *attributes)
1185{
1186 MagickBooleanType
1187 status;
1188
1189 if (path == (const char *) NULL)
1190 {
1191 errno=EINVAL;
1192 return(MagickFalse);
1193 }
1194#if !defined(MAGICKCORE_HAVE__WSTAT)
1195 status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
1196#else
1197 {
1198 wchar_t
1199 *unicode_path;
1200
1201 unicode_path=ConvertUTF8ToUTF16(path);
1202 if (unicode_path == (wchar_t *) NULL)
1203 return(MagickFalse);
1204 status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
1205 MagickFalse;
1206 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1207 }
1208#endif
1209 return(status);
1210}
1211
1212/*
1213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1214% %
1215% %
1216% %
1217% G e t P a t h C o m p o n e n t %
1218% %
1219% %
1220% %
1221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222%
1223% GetPathComponent() returns the parent directory name, filename, basename, or
1224% extension of a file path.
1225%
1226% The format of the GetPathComponent function is:
1227%
1228% GetPathComponent(const char *path,PathType type,char *component)
1229%
1230% A description of each parameter follows:
1231%
1232% o path: Specifies a pointer to a character array that contains the
1233% file path.
1234%
1235% o type: Specififies which file path component to return.
1236%
1237% o component: the selected file path component is returned here.
1238%
1239*/
1240MagickExport void GetPathComponent(const char *path,PathType type,
1241 char *component)
1242{
1243 char
1244 magick[MaxTextExtent],
1245 *q,
1246 subimage[MaxTextExtent];
1247
1248 register char
1249 *p;
1250
1251 assert(path != (const char *) NULL);
1252 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1253 assert(component != (char *) NULL);
1254 if (*path == '\0')
1255 {
1256 *component='\0';
1257 return;
1258 }
1259 (void) CopyMagickString(component,path,MaxTextExtent);
1260 *magick='\0';
1261#if defined(__OS2__)
1262 if (path[1] != ":")
1263#endif
1264 for (p=component; *p != '\0'; p++)
1265 if ((*p == ':') && (IsPathDirectory(path) < 0) &&
1266 (IsPathAccessible(path) == MagickFalse))
1267 {
1268 /*
1269 Look for image format specification (e.g. ps3:image).
1270 */
1271 (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1272 if (IsMagickConflict(magick) != MagickFalse)
1273 *magick='\0';
1274 else
1275 for (q=component; *q != '\0'; q++)
1276 *q=(*++p);
1277 break;
1278 }
1279 *subimage='\0';
1280 p=component;
1281 if (*p != '\0')
1282 p=component+strlen(component)-1;
1283 if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1284 (IsPathAccessible(path) == MagickFalse))
1285 {
1286 /*
1287 Look for scene specification (e.g. img0001.pcd[4]).
1288 */
1289 for (q=p-1; q > component; q--)
1290 if (*q == '[')
1291 break;
1292 if (*q == '[')
1293 {
1294 (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1295 subimage[p-q-1]='\0';
1296 if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1297 (IsGeometry(subimage) == MagickFalse))
1298 *subimage='\0';
1299 else
1300 *q='\0';
1301 }
1302 }
1303 p=component;
1304 if (*p != '\0')
1305 for (p=component+strlen(component)-1; p > component; p--)
1306 if (IsBasenameSeparator(*p) != MagickFalse)
1307 break;
1308 switch (type)
1309 {
1310 case MagickPath:
1311 {
1312 (void) CopyMagickString(component,magick,MaxTextExtent);
1313 break;
1314 }
1315 case RootPath:
1316 {
1317 for (p=component+(strlen(component)-1); p > component; p--)
1318 {
1319 if (IsBasenameSeparator(*p) != MagickFalse)
1320 break;
1321 if (*p == '.')
1322 break;
1323 }
1324 if (*p == '.')
1325 *p='\0';
1326 break;
1327 }
1328 case HeadPath:
1329 {
1330 *p='\0';
1331 break;
1332 }
1333 case TailPath:
1334 {
1335 if (IsBasenameSeparator(*p) != MagickFalse)
1336 (void) CopyMagickMemory((unsigned char *) component,
1337 (const unsigned char *) (p+1),strlen(p+1)+1);
1338 break;
1339 }
1340 case BasePath:
1341 {
1342 if (IsBasenameSeparator(*p) != MagickFalse)
1343 (void) CopyMagickString(component,p+1,MaxTextExtent);
1344 for (p=component+(strlen(component)-1); p > component; p--)
1345 if (*p == '.')
1346 {
1347 *p='\0';
1348 break;
1349 }
1350 break;
1351 }
1352 case ExtensionPath:
1353 {
1354 if (IsBasenameSeparator(*p) != MagickFalse)
1355 (void) CopyMagickString(component,p+1,MaxTextExtent);
1356 p=component;
1357 if (*p != '\0')
1358 for (p=component+strlen(component)-1; p > component; p--)
1359 if (*p == '.')
1360 break;
1361 *component='\0';
1362 if (*p == '.')
1363 (void) CopyMagickString(component,p+1,MaxTextExtent);
1364 break;
1365 }
1366 case SubimagePath:
1367 {
1368 (void) CopyMagickString(component,subimage,MaxTextExtent);
1369 break;
1370 }
1371 case CanonicalPath:
1372 case UndefinedPath:
1373 break;
1374 }
1375}
1376
1377/*
1378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379% %
1380% %
1381% %
1382% G e t P a t h C o m p o n e n t s %
1383% %
1384% %
1385% %
1386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387%
1388% GetPathComponents() returns a list of path components.
1389%
1390% The format of the GetPathComponents method is:
1391%
1392% char **GetPathComponents(const char *path,
1393% unsigned long *number_componenets)
1394%
1395% A description of each parameter follows:
1396%
1397% o path: Specifies the string to segment into a list.
1398%
1399% o number_components: return the number of components in the list
1400%
1401*/
1402MagickExport char **GetPathComponents(const char *path,
1403 unsigned long *number_components)
1404{
1405 char
1406 **components;
1407
1408 register const char
1409 *p,
1410 *q;
1411
1412 register long
1413 i;
1414
1415 if (path == (char *) NULL)
1416 return((char **) NULL);
1417 *number_components=1;
1418 for (p=path; *p != '\0'; p++)
1419 if (IsBasenameSeparator(*p))
1420 (*number_components)++;
1421 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1422 sizeof(*components));
1423 if (components == (char **) NULL)
1424 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1425 p=path;
1426 for (i=0; i < (long) *number_components; i++)
1427 {
1428 for (q=p; *q != '\0'; q++)
1429 if (IsBasenameSeparator(*q))
1430 break;
1431 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1432 sizeof(*components));
1433 if (components[i] == (char *) NULL)
1434 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1435 (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1436 p=q+1;
1437 }
1438 components[i]=(char *) NULL;
1439 return(components);
1440}
1441
1442/*
1443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444% %
1445% %
1446% %
1447% I s P a t h A c c e s s i b l e %
1448% %
1449% %
1450% %
1451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1452%
1453% IsPathAccessible() returns MagickTrue if the file as defined by the path is
1454% accessible.
1455%
1456% The format of the IsPathAccessible method is:
1457%
1458% MagickBooleanType IsPathAccessible(const char *filename)
1459%
1460% A description of each parameter follows.
1461%
1462% o path: Specifies a path to a file.
1463%
1464*/
1465MagickExport MagickBooleanType IsPathAccessible(const char *path)
1466{
1467 MagickBooleanType
1468 status;
1469
1470 struct stat
1471 attributes;
1472
1473 if ((path == (const char *) NULL) || (*path == '\0'))
1474 return(MagickFalse);
1475 status=GetPathAttributes(path,&attributes);
1476 if (status == MagickFalse)
1477 return(status);
1478 if (S_ISREG(attributes.st_mode) == 0)
1479 return(MagickFalse);
1480 if (access(path,F_OK) != 0)
1481 return(MagickFalse);
1482 return(MagickTrue);
1483}
1484
1485/*
1486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1487% %
1488% %
1489% %
1490+ I s P a t h D i r e c t o r y %
1491% %
1492% %
1493% %
1494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1495%
1496% IsPathDirectory() returns -1 if the directory does not exist, 1 is returned
1497% if the path represents a directory otherwise 0.
1498%
1499% The format of the IsPathDirectory method is:
1500%
1501% int IsPathDirectory(const char *path)
1502%
1503% A description of each parameter follows.
1504%
1505% o path: The directory path.
1506%
1507*/
1508static int IsPathDirectory(const char *path)
1509{
1510 MagickBooleanType
1511 status;
1512
1513 struct stat
1514 attributes;
1515
1516 if ((path == (const char *) NULL) || (*path == '\0'))
1517 return(MagickFalse);
1518 status=GetPathAttributes(path,&attributes);
1519 if (status == MagickFalse)
1520 return(-1);
1521 if (S_ISDIR(attributes.st_mode) == 0)
1522 return(0);
1523 return(1);
1524}
1525
1526/*
1527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528% %
1529% %
1530% %
1531% I s M a g i c k T r u e %
1532% %
1533% %
1534% %
1535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536%
1537% IsMagickTrue() returns MagickTrue if the value is "true", "on", "yes" or
1538% "1".
1539%
1540% The format of the IsMagickTrue method is:
1541%
1542% MagickBooleanType IsMagickTrue(const char *value)
1543%
1544% A description of each parameter follows:
1545%
1546% o option: either MagickTrue or MagickFalse depending on the value
1547% parameter.
1548%
1549% o value: Specifies a pointer to a character array.
1550%
1551*/
1552MagickExport MagickBooleanType IsMagickTrue(const char *value)
1553{
1554 if (value == (const char *) NULL)
1555 return(MagickFalse);
1556 if (LocaleCompare(value,"true") == 0)
1557 return(MagickTrue);
1558 if (LocaleCompare(value,"on") == 0)
1559 return(MagickTrue);
1560 if (LocaleCompare(value,"yes") == 0)
1561 return(MagickTrue);
1562 if (LocaleCompare(value,"1") == 0)
1563 return(MagickTrue);
1564 return(MagickFalse);
1565}
1566
1567/*
1568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1569% %
1570% %
1571% %
1572% L i s t F i l e s %
1573% %
1574% %
1575% %
1576%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1577%
1578% ListFiles() reads the directory specified and returns a list of filenames
1579% contained in the directory sorted in ascending alphabetic order.
1580%
1581% The format of the ListFiles function is:
1582%
1583% char **ListFiles(const char *directory,const char *pattern,
1584% long *number_entries)
1585%
1586% A description of each parameter follows:
1587%
1588% o filelist: Method ListFiles returns a list of filenames contained
1589% in the directory. If the directory specified cannot be read or it is
1590% a file a NULL list is returned.
1591%
1592% o directory: Specifies a pointer to a text string containing a directory
1593% name.
1594%
1595% o pattern: Specifies a pointer to a text string containing a pattern.
1596%
1597% o number_entries: This integer returns the number of filenames in the
1598% list.
1599%
1600*/
1601
1602#if defined(__cplusplus) || defined(c_plusplus)
1603extern "C" {
1604#endif
1605
1606static int FileCompare(const void *x,const void *y)
1607{
1608 register const char
1609 **p,
1610 **q;
1611
1612 p=(const char **) x;
1613 q=(const char **) y;
1614 return(LocaleCompare(*p,*q));
1615}
1616
1617#if defined(__cplusplus) || defined(c_plusplus)
1618}
1619#endif
1620
1621static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1622 struct dirent **result)
1623{
1624#if defined(MAGICKCORE_HAVE_READDIR_R)
1625 return(readdir_r(directory,entry,result));
1626#else
1627 (void) entry;
1628 errno=0;
1629 *result=readdir(directory);
1630 return(errno);
1631#endif
1632}
1633
1634MagickExport char **ListFiles(const char *directory,const char *pattern,
1635 unsigned long *number_entries)
1636{
1637 char
1638 **filelist;
1639
1640 DIR
1641 *current_directory;
1642
1643 struct dirent
1644 *buffer,
1645 *entry;
1646
1647 unsigned long
1648 max_entries;
1649
1650 /*
1651 Open directory.
1652 */
1653 assert(directory != (const char *) NULL);
1654 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1655 assert(pattern != (const char *) NULL);
1656 assert(number_entries != (unsigned long *) NULL);
1657 *number_entries=0;
1658 current_directory=opendir(directory);
1659 if (current_directory == (DIR *) NULL)
1660 return((char **) NULL);
1661 /*
1662 Allocate filelist.
1663 */
1664 max_entries=2048;
1665 filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1666 sizeof(*filelist));
1667 if (filelist == (char **) NULL)
1668 {
1669 (void) closedir(current_directory);
1670 return((char **) NULL);
1671 }
1672 /*
1673 Save the current and change to the new directory.
1674 */
1675 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
1676 if (buffer == (struct dirent *) NULL)
1677 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1678 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1679 (entry != (struct dirent *) NULL))
1680 {
1681 if (*entry->d_name == '.')
1682 continue;
1683 if ((IsPathDirectory(entry->d_name) > 0) ||
1684#if defined(__WINDOWS__)
1685 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1686#else
1687 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1688#endif
1689 {
1690 if (*number_entries >= max_entries)
1691 {
1692 /*
1693 Extend the file list.
1694 */
1695 max_entries<<=1;
1696 filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1697 max_entries,sizeof(*filelist));
1698 if (filelist == (char **) NULL)
1699 break;
1700 }
1701#if defined(vms)
1702 {
1703 register char
1704 *p;
1705
1706 p=strchr(entry->d_name,';');
1707 if (p)
1708 *p='\0';
1709 if (*number_entries > 0)
1710 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1711 continue;
1712 }
1713#endif
1714 filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1715 if (IsPathDirectory(entry->d_name) > 0)
1716 (void) ConcatenateMagickString(filelist[*number_entries],
1717 DirectorySeparator,MaxTextExtent);
1718 (*number_entries)++;
1719 }
1720 }
1721 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1722 (void) closedir(current_directory);
1723 if (filelist == (char **) NULL)
1724 return((char **) NULL);
1725 /*
1726 Sort filelist in ascending order.
1727 */
1728 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1729 FileCompare);
1730 return(filelist);
1731}
1732
1733/*
1734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1735% %
1736% %
1737% %
1738% M u l t i l i n e C e n s u s %
1739% %
1740% %
1741% %
1742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1743%
1744% MultilineCensus() returns the number of lines within a label. A line is
1745% represented by a \n character.
1746%
1747% The format of the MultilineCenus method is:
1748%
1749% unsigned long MultilineCensus(const char *label)
1750%
1751% A description of each parameter follows.
1752%
1753% o label: This character string is the label.
1754%
1755%
1756*/
1757MagickExport unsigned long MultilineCensus(const char *label)
1758{
1759 unsigned long
1760 number_lines;
1761
1762 /*
1763 Determine the number of lines within this label.
1764 */
1765 if (label == (char *) NULL)
1766 return(0);
1767 for (number_lines=1; *label != '\0'; label++)
1768 if (*label == '\n')
1769 number_lines++;
1770 return(number_lines);
1771}
1772
1773/*
1774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775% %
1776% %
1777% %
1778% O p e n M a g i c k S t r e a m %
1779% %
1780% %
1781% %
1782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1783%
1784% OpenMagickStream() opens the file at the specified path and return the
1785% associated stream.
1786%
1787% The path of the OpenMagickStream method is:
1788%
1789% FILE *OpenMagickStream(const char *path,const char *mode)
1790%
1791% A description of each parameter follows.
1792%
1793% o path: the file path.
1794%
1795% o mode: the file mode.
1796%
1797*/
1798MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
1799{
1800 FILE
1801 *file;
1802
1803 if ((path == (const char *) NULL) || (mode == (const char *) NULL))
1804 {
1805 errno=EINVAL;
1806 return((FILE *) NULL);
1807 }
1808 file=(FILE *) NULL;
1809#if defined(MAGICKCORE_HAVE__WFOPEN)
1810 {
1811 wchar_t
1812 *unicode_mode,
1813 *unicode_path;
1814
1815 unicode_path=ConvertUTF8ToUTF16(path);
1816 if (unicode_path == (wchar_t *) NULL)
1817 return((FILE *) NULL);
1818 unicode_mode=ConvertUTF8ToUTF16(mode);
1819 if (unicode_mode == (wchar_t *) NULL)
1820 {
1821 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1822 return((FILE *) NULL);
1823 }
1824 file=_wfopen(unicode_path,unicode_mode);
1825 unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
1826 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1827 }
1828#endif
1829 if (file == (FILE *) NULL)
1830 file=fopen(path,mode);
1831 return(file);
1832}
1833
1834/*
1835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1836% %
1837% %
1838% %
1839% S y s t e m C o m m a n d %
1840% %
1841% %
1842% %
1843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1844%
1845% SystemCommand() executes the specified command and waits until it
1846% terminates. The returned value is the exit status of the command.
1847%
1848% The format of the SystemCommand method is:
1849%
cristyb32b90a2009-09-07 21:45:48 +00001850% int SystemCommand(const MagickBooleanType verbose,const char *command,
1851% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001852%
1853% A description of each parameter follows:
1854%
cristyb32b90a2009-09-07 21:45:48 +00001855% o verbose: a value other than 0 prints the executed command before it is
cristy3ed852e2009-09-05 21:47:34 +00001856% invoked.
1857%
cristyb32b90a2009-09-07 21:45:48 +00001858% o command: this string is the command to execute.
1859%
1860% o exception: return any errors here.
cristy3ed852e2009-09-05 21:47:34 +00001861%
1862*/
1863MagickExport int SystemCommand(const MagickBooleanType verbose,
cristyb32b90a2009-09-07 21:45:48 +00001864 const char *command,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001865{
cristyb32b90a2009-09-07 21:45:48 +00001866 char
1867 **arguments;
1868
cristy3ed852e2009-09-05 21:47:34 +00001869 int
cristyb32b90a2009-09-07 21:45:48 +00001870 number_arguments,
cristy3ed852e2009-09-05 21:47:34 +00001871 status;
1872
cristyb32b90a2009-09-07 21:45:48 +00001873 PolicyDomain
1874 domain;
1875
1876 PolicyRights
1877 rights;
1878
1879 register long
1880 i;
1881
1882 status=(-1);
1883 arguments=StringToArgv(command,&number_arguments);
1884 if (arguments == (char **) NULL)
1885 return(status);
1886 domain=DelegatePolicyDomain;
1887 rights=ExecutePolicyRights;
1888 if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
1889 {
1890 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1891 "NotAuthorized","`%s'",arguments[1]);
1892 for (i=0; i < number_arguments; i++)
1893 arguments[i]=DestroyString(arguments[i]);
1894 arguments=(char **) RelinquishMagickMemory(arguments);
1895 return(-1);
1896 }
cristy3ed852e2009-09-05 21:47:34 +00001897 if (verbose != MagickFalse)
1898 {
1899 (void) fprintf(stderr,"%s\n",command);
1900 (void) fflush(stderr);
1901 }
cristy3ed852e2009-09-05 21:47:34 +00001902#if defined(MAGICKCORE_POSIX_SUPPORT)
1903#if !defined(MAGICKCORE_HAVE_EXECVP)
1904 status=system(command);
1905#else
1906 if (strspn(command,"&;<>|") == 0)
1907 status=system(command);
1908 else
1909 {
cristyb32b90a2009-09-07 21:45:48 +00001910 pid_t
1911 child_pid;
cristy3ed852e2009-09-05 21:47:34 +00001912
cristyb32b90a2009-09-07 21:45:48 +00001913 /*
1914 Call application directly rather than from a shell.
1915 */
1916 child_pid=fork();
1917 if (child_pid == (pid_t) -1)
cristy3ed852e2009-09-05 21:47:34 +00001918 status=system(command);
1919 else
cristyb32b90a2009-09-07 21:45:48 +00001920 if (child_pid == 0)
1921 {
1922 status=execvp(arguments[1],arguments+1);
1923 _exit(1);
1924 }
1925 else
1926 {
1927 int
1928 child_status;
cristy3ed852e2009-09-05 21:47:34 +00001929
cristyb32b90a2009-09-07 21:45:48 +00001930 pid_t
1931 pid;
cristy3ed852e2009-09-05 21:47:34 +00001932
cristyb32b90a2009-09-07 21:45:48 +00001933 child_status=0;
1934 pid=waitpid(child_pid,&child_status,0);
1935 if (pid == -1)
1936 status=(-1);
cristy3ed852e2009-09-05 21:47:34 +00001937 else
1938 {
cristyb32b90a2009-09-07 21:45:48 +00001939 if (WIFEXITED(child_status) != 0)
1940 status=WEXITSTATUS(child_status);
cristy3ed852e2009-09-05 21:47:34 +00001941 else
cristyb32b90a2009-09-07 21:45:48 +00001942 if (WIFSIGNALED(child_status))
1943 status=(-1);
cristy3ed852e2009-09-05 21:47:34 +00001944 }
cristyb32b90a2009-09-07 21:45:48 +00001945 }
cristy3ed852e2009-09-05 21:47:34 +00001946 }
1947#endif
1948#elif defined(__WINDOWS__)
1949 status=NTSystemCommand(command);
1950#elif defined(macintosh)
1951 status=MACSystemCommand(command);
1952#elif defined(vms)
1953 status=system(command);
1954#else
1955# error No suitable system() method.
1956#endif
1957 if (status < 0)
1958 {
1959 char
1960 *message;
1961
cristy3ed852e2009-09-05 21:47:34 +00001962 message=GetExceptionMessage(errno);
1963 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
1964 "`%s': %s",command,message);
1965 message=DestroyString(message);
cristy3ed852e2009-09-05 21:47:34 +00001966 }
cristyb32b90a2009-09-07 21:45:48 +00001967 for (i=0; i < number_arguments; i++)
1968 arguments[i]=DestroyString(arguments[i]);
1969 arguments=(char **) RelinquishMagickMemory(arguments);
cristy3ed852e2009-09-05 21:47:34 +00001970 return(status);
1971}