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