MagickCore 6.9.12-98
Convert, Edit, Or Compose Bitmap Images
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
1044 uint32_t
1045 length;
1046
1047 length=sizeof(executable_path);
1048 if (_NSGetExecutablePath(executable_path,&length) == 0)
1049 {
1050 char
1051 *real_path = realpath_utf8(executable_path);
1052
1053 if (real_path != (char *) NULL)
1054 {
1055 (void) CopyMagickString(path,real_path,extent);
1056 real_path=DestroyString(real_path);
1057 }
1058 }
1059 }
1060#endif
1061#if defined(MAGICKCORE_HAVE_GETEXECNAME)
1062 {
1063 const char
1064 *execution_path;
1065
1066 execution_path=(const char *) getexecname();
1067 if (execution_path != (const char *) NULL)
1068 {
1069 if (*execution_path != *DirectorySeparator)
1070 (void) ConcatenateMagickString(path,DirectorySeparator,extent);
1071 (void) ConcatenateMagickString(path,execution_path,extent);
1072 }
1073 }
1074#endif
1075#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1076 NTGetExecutionPath(path,extent);
1077#endif
1078#if defined(__GNU__)
1079 {
1080 char
1081 *program_name;
1082
1083 ssize_t
1084 count;
1085
1086 count=0;
1087 program_name=program_invocation_name;
1088 if (*program_invocation_name != '/')
1089 {
1090 size_t
1091 extent;
1092
1093 extent=strlen(directory)+strlen(program_name)+2;
1094 program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1095 if (program_name == (char *) NULL)
1096 program_name=program_invocation_name;
1097 else
1098 count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1099 program_invocation_name);
1100 }
1101 if (count != -1)
1102 {
1103 char
1104 *real_path = realpath_utf8(program_name);
1105
1106 if (real_path != (char *) NULL)
1107 {
1108 (void) CopyMagickString(path,real_path,extent);
1109 real_path=DestroyString(real_path);
1110 }
1111 }
1112 if (program_name != program_invocation_name)
1113 program_name=(char *) RelinquishMagickMemory(program_name);
1114 }
1115#endif
1116#if defined(__OpenBSD__)
1117 {
1118 extern char
1119 *__progname;
1120
1121 (void) CopyMagickString(path,__progname,extent);
1122 }
1123#endif
1124 return(IsPathAccessible(path));
1125}
1126
1127/*
1128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1129% %
1130% %
1131% %
1132% G e t M a g i c k P a g e S i z e %
1133% %
1134% %
1135% %
1136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1137%
1138% GetMagickPageSize() returns the memory page size.
1139%
1140% The format of the GetMagickPageSize method is:
1141%
1142% ssize_t GetMagickPageSize()
1143%
1144*/
1145MagickExport ssize_t GetMagickPageSize(void)
1146{
1147 static ssize_t
1148 page_size = -1;
1149
1150 if (page_size > 0)
1151 return(page_size);
1152#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1153 page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1154#elif defined(MAGICKCORE_HAVE_GETPAGESIZE)
1155 page_size=(ssize_t) getpagesize();
1156#endif
1157 if (page_size <= 0)
1158 page_size=4096;
1159 return(page_size);
1160}
1161
1162/*
1163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164% %
1165% %
1166% %
1167% G e t P a t h A t t r i b u t e s %
1168% %
1169% %
1170% %
1171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172%
1173% GetPathAttributes() returns attributes (e.g. size of file) about a path.
1174%
1175% The path of the GetPathAttributes method is:
1176%
1177% MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1178%
1179% A description of each parameter follows.
1180%
1181% o path: the file path.
1182%
1183% o attributes: the path attributes are returned here.
1184%
1185*/
1186MagickExport MagickBooleanType GetPathAttributes(const char *path,
1187 void *attributes)
1188{
1189 MagickBooleanType
1190 status;
1191
1192 if (path == (const char *) NULL)
1193 {
1194 errno=EINVAL;
1195 return(MagickFalse);
1196 }
1197 (void) memset(attributes,0,sizeof(struct stat));
1198 status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
1199 MagickFalse;
1200 return(status);
1201}
1202
1203/*
1204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1205% %
1206% %
1207% %
1208% G e t P a t h C o m p o n e n t %
1209% %
1210% %
1211% %
1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1213%
1214% GetPathComponent() returns the parent directory name, filename, basename, or
1215% extension of a file path.
1216%
1217% The component string pointed to must have at least MaxTextExtent space
1218% for the results to be stored.
1219%
1220% The format of the GetPathComponent function is:
1221%
1222% GetPathComponent(const char *path,PathType type,char *component)
1223%
1224% A description of each parameter follows:
1225%
1226% o path: Specifies a pointer to a character array that contains the
1227% file path.
1228%
1229% o type: Specifies which file path component to return.
1230%
1231% o component: the selected file path component is returned here.
1232%
1233*/
1234MagickExport void GetPathComponent(const char *path,PathType type,
1235 char *component)
1236{
1237 char
1238 *q;
1239
1240 char
1241 *p;
1242
1243 size_t
1244 magick_length,
1245 subimage_offset,
1246 subimage_length;
1247
1248 assert(path != (const char *) NULL);
1249 assert(component != (char *) NULL);
1250 if (IsEventLogging() != MagickFalse)
1251 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1252 if (*path == '\0')
1253 {
1254 *component='\0';
1255 return;
1256 }
1257 (void) CopyMagickString(component,path,MagickPathExtent);
1258 subimage_length=0;
1259 subimage_offset=0;
1260 if (type != SubcanonicalPath)
1261 {
1262 p=component+strlen(component)-1;
1263 if ((strlen(component) > 2) && (*p == ']'))
1264 {
1265 q=strrchr(component,'[');
1266 if ((q != (char *) NULL) && ((q == component) || (*(q-1) != ']')) &&
1267 (IsPathAccessible(path) == MagickFalse))
1268 {
1269 /*
1270 Look for scene specification (e.g. img0001.pcd[4]).
1271 */
1272 *p='\0';
1273 if ((IsSceneGeometry(q+1,MagickFalse) == MagickFalse) &&
1274 (IsGeometry(q+1) == MagickFalse))
1275 *p=']';
1276 else
1277 {
1278 subimage_length=(size_t) (p-q);
1279 subimage_offset=(size_t) (q-component+1);
1280 *q='\0';
1281 }
1282 }
1283 }
1284 }
1285 magick_length=0;
1286#if defined(__OS2__)
1287 if (path[1] != ":")
1288#endif
1289 for (p=component; *p != '\0'; p++)
1290 {
1291 if ((*p == '%') && (*(p+1) == '['))
1292 {
1293 /*
1294 Skip over %[...].
1295 */
1296 for (p++; (*p != ']') && (*p != '\0'); p++) ;
1297 if (*p == '\0')
1298 break;
1299 }
1300 if ((p != component) && (*p == ':') && (IsPathDirectory(component) < 0) &&
1301 (IsPathAccessible(component) == MagickFalse))
1302 {
1303 /*
1304 Look for image format specification (e.g. ps3:image).
1305 */
1306 *p='\0';
1307 if (IsMagickConflict(component) != MagickFalse)
1308 *p=':';
1309 else
1310 {
1311 magick_length=(size_t) (p-component+1);
1312 for (q=component; *(++p) != '\0'; q++)
1313 *q=(*p);
1314 *q='\0';
1315 }
1316 break;
1317 }
1318 }
1319 p=component;
1320 if (*p != '\0')
1321 for (p=component+strlen(component)-1; p > component; p--)
1322 if (IsBasenameSeparator(*p) != MagickFalse)
1323 break;
1324 switch (type)
1325 {
1326 case MagickPath:
1327 {
1328 if (magick_length != 0)
1329 (void) CopyMagickString(component,path,magick_length);
1330 else
1331 *component='\0';
1332 break;
1333 }
1334 case RootPath:
1335 {
1336 if (*component != '\0')
1337 {
1338 for (p=component+(strlen(component)-1); p > component; p--)
1339 {
1340 if (IsBasenameSeparator(*p) != MagickFalse)
1341 break;
1342 if (*p == '.')
1343 break;
1344 }
1345 if (*p == '.')
1346 *p='\0';
1347 break;
1348 }
1349 magick_fallthrough;
1350 }
1351 case HeadPath:
1352 {
1353 *p='\0';
1354 break;
1355 }
1356 case TailPath:
1357 {
1358 if (IsBasenameSeparator(*p) != MagickFalse)
1359 (void) CopyMagickString(component,p+1,MagickPathExtent);
1360 break;
1361 }
1362 case BasePath:
1363 {
1364 if (IsBasenameSeparator(*p) != MagickFalse)
1365 (void) CopyMagickString(component,p+1,MagickPathExtent);
1366 if (*component != '\0')
1367 for (p=component+(strlen(component)-1); p > component; p--)
1368 if (*p == '.')
1369 {
1370 *p='\0';
1371 break;
1372 }
1373 break;
1374 }
1375 case BasePathSansCompressExtension:
1376 {
1377 char
1378 extension[MagickPathExtent];
1379
1380 /*
1381 Base path sans any compression extension.
1382 */
1383 GetPathComponent(path,ExtensionPath,extension);
1384 if ((LocaleCompare(extension,"bz2") == 0) ||
1385 (LocaleCompare(extension,"gz") == 0) ||
1386 (LocaleCompare(extension,"svgz") == 0) ||
1387 (LocaleCompare(extension,"wmz") == 0) ||
1388 (LocaleCompare(extension,"Z") == 0))
1389 GetPathComponent(path,BasePath,component);
1390 break;
1391 }
1392 case ExtensionPath:
1393 {
1394 if (IsBasenameSeparator(*p) != MagickFalse)
1395 (void) CopyMagickString(component,p+1,MagickPathExtent);
1396 if (*component != '\0')
1397 for (p=component+strlen(component)-1; p > component; p--)
1398 if (*p == '.')
1399 break;
1400 *component='\0';
1401 if (*p == '.')
1402 (void) CopyMagickString(component,p+1,MagickPathExtent);
1403 break;
1404 }
1405 case SubimagePath:
1406 {
1407 *component='\0';
1408 if ((subimage_length != 0) && (magick_length < subimage_offset))
1409 (void) CopyMagickString(component,path+subimage_offset,subimage_length);
1410 break;
1411 }
1412 case SubcanonicalPath:
1413 case CanonicalPath:
1414 case UndefinedPath:
1415 break;
1416 }
1417}
1418
1419/*
1420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1421% %
1422% %
1423% %
1424% G e t P a t h C o m p o n e n t s %
1425% %
1426% %
1427% %
1428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429%
1430% GetPathComponents() returns a list of path components.
1431%
1432% The format of the GetPathComponents method is:
1433%
1434% char **GetPathComponents(const char *path,
1435% size_t *number_components)
1436%
1437% A description of each parameter follows:
1438%
1439% o path: Specifies the string to segment into a list.
1440%
1441% o number_components: return the number of components in the list
1442%
1443*/
1444MagickExport char **GetPathComponents(const char *path,
1445 size_t *number_components)
1446{
1447 char
1448 **components;
1449
1450 const char
1451 *p,
1452 *q;
1453
1454 ssize_t
1455 i;
1456
1457 if (path == (char *) NULL)
1458 return((char **) NULL);
1459 *number_components=1;
1460 for (p=path; *p != '\0'; p++)
1461 if (IsBasenameSeparator(*p))
1462 (*number_components)++;
1463 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1464 sizeof(*components));
1465 if (components == (char **) NULL)
1466 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1467 p=path;
1468 for (i=0; i < (ssize_t) *number_components; i++)
1469 {
1470 for (q=p; *q != '\0'; q++)
1471 if (IsBasenameSeparator(*q))
1472 break;
1473 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1474 sizeof(**components));
1475 if (components[i] == (char *) NULL)
1476 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1477 (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1478 p=q+1;
1479 }
1480 components[i]=(char *) NULL;
1481 return(components);
1482}
1483
1484/*
1485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1486% %
1487% %
1488% %
1489% I s P a t h A c c e s s i b l e %
1490% %
1491% %
1492% %
1493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1494%
1495% IsPathAccessible() returns MagickTrue if the file as defined by the path is
1496% accessible.
1497%
1498% The format of the IsPathAccessible method is:
1499%
1500% MagickBooleanType IsPathAccessible(const char *path)
1501%
1502% A description of each parameter follows.
1503%
1504% o path: Specifies a path to a file.
1505%
1506*/
1507MagickExport MagickBooleanType IsPathAccessible(const char *path)
1508{
1509 MagickBooleanType
1510 status;
1511
1512 struct stat
1513 attributes;
1514
1515 if ((path == (const char *) NULL) || (*path == '\0'))
1516 return(MagickFalse);
1517 if (LocaleCompare(path,"-") == 0)
1518 return(MagickTrue);
1519 status=GetPathAttributes(path,&attributes);
1520 if (status == MagickFalse)
1521 return(status);
1522 if (S_ISREG(attributes.st_mode) == 0)
1523 return(MagickFalse);
1524 if (access_utf8(path,F_OK) != 0)
1525 return(MagickFalse);
1526 return(MagickTrue);
1527}
1528
1529/*
1530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1531% %
1532% %
1533% %
1534+ I s P a t h D i r e c t o r y %
1535% %
1536% %
1537% %
1538%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1539%
1540% IsPathDirectory() returns -1 if the directory does not exist, 1 is returned
1541% if the path represents a directory otherwise 0.
1542%
1543% The format of the IsPathDirectory method is:
1544%
1545% int IsPathDirectory(const char *path)
1546%
1547% A description of each parameter follows.
1548%
1549% o path: The directory path.
1550%
1551*/
1552static int IsPathDirectory(const char *path)
1553{
1554 MagickBooleanType
1555 status;
1556
1557 struct stat
1558 attributes;
1559
1560 if ((path == (const char *) NULL) || (*path == '\0'))
1561 return(MagickFalse);
1562 status=GetPathAttributes(path,&attributes);
1563 if (status == MagickFalse)
1564 return(-1);
1565 if (S_ISDIR(attributes.st_mode) == 0)
1566 return(0);
1567 return(1);
1568}
1569
1570/*
1571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1572% %
1573% %
1574% %
1575% L i s t F i l e s %
1576% %
1577% %
1578% %
1579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1580%
1581% ListFiles() reads the directory specified and returns a list of filenames
1582% contained in the directory sorted in ascending alphabetic order.
1583%
1584% The format of the ListFiles function is:
1585%
1586% char **ListFiles(const char *directory,const char *pattern,
1587% ssize_t *number_entries)
1588%
1589% A description of each parameter follows:
1590%
1591% o filelist: Method ListFiles returns a list of filenames contained
1592% in the directory. If the directory specified cannot be read or it is
1593% a file a NULL list is returned.
1594%
1595% o directory: Specifies a pointer to a text string containing a directory
1596% name.
1597%
1598% o pattern: Specifies a pointer to a text string containing a pattern.
1599%
1600% o number_entries: This integer returns the number of filenames in the
1601% list.
1602%
1603*/
1604
1605#if defined(__cplusplus) || defined(c_plusplus)
1606extern "C" {
1607#endif
1608
1609static int FileCompare(const void *x,const void *y)
1610{
1611 const char
1612 **p,
1613 **q;
1614
1615 p=(const char **) x;
1616 q=(const char **) y;
1617 return(LocaleCompare(*p,*q));
1618}
1619
1620#if defined(__cplusplus) || defined(c_plusplus)
1621}
1622#endif
1623
1624MagickExport char **ListFiles(const char *directory,const char *pattern,
1625 size_t *number_entries)
1626{
1627 char
1628 **filelist;
1629
1630 DIR
1631 *current_directory;
1632
1633 struct dirent
1634 *buffer,
1635 *entry;
1636
1637 size_t
1638 max_entries;
1639
1640 /*
1641 Open directory.
1642 */
1643 assert(directory != (const char *) NULL);
1644 assert(pattern != (const char *) NULL);
1645 assert(number_entries != (size_t *) NULL);
1646 if (IsEventLogging() != MagickFalse)
1647 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1648 *number_entries=0;
1649 current_directory=opendir(directory);
1650 if (current_directory == (DIR *) NULL)
1651 return((char **) NULL);
1652 /*
1653 Allocate filelist.
1654 */
1655 max_entries=2048;
1656 filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1657 sizeof(*filelist));
1658 if (filelist == (char **) NULL)
1659 {
1660 (void) closedir(current_directory);
1661 return((char **) NULL);
1662 }
1663 /*
1664 Save the current and change to the new directory.
1665 */
1666 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
1667 if (buffer == (struct dirent *) NULL)
1668 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1669 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1670 (entry != (struct dirent *) NULL))
1671 {
1672 if ((LocaleCompare(entry->d_name,".") == 0) ||
1673 (LocaleCompare(entry->d_name,"..") == 0))
1674 continue;
1675 if ((IsPathDirectory(entry->d_name) > 0) ||
1676#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1677 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1678#else
1679 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1680#endif
1681 {
1682 if (*number_entries >= max_entries)
1683 {
1684 /*
1685 Extend the file list.
1686 */
1687 max_entries<<=1;
1688 filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1689 max_entries,sizeof(*filelist));
1690 if (filelist == (char **) NULL)
1691 break;
1692 }
1693#if defined(vms)
1694 {
1695 char
1696 *p;
1697
1698 p=strchr(entry->d_name,';');
1699 if (p)
1700 *p='\0';
1701 if (*number_entries > 0)
1702 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1703 continue;
1704 }
1705#endif
1706 filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1707 (*number_entries)++;
1708 }
1709 }
1710 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1711 (void) closedir(current_directory);
1712 if (filelist == (char **) NULL)
1713 return((char **) NULL);
1714 /*
1715 Sort filelist in ascending order.
1716 */
1717 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1718 FileCompare);
1719 return(filelist);
1720}
1721
1722/*
1723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724% %
1725% %
1726% %
1727% M a g i c k D e l a y %
1728% %
1729% %
1730% %
1731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1732%
1733% MagickDelay() suspends program execution for the number of milliseconds
1734% specified.
1735%
1736% The format of the Delay method is:
1737%
1738% void MagickDelay(const MagickSizeType milliseconds)
1739%
1740% A description of each parameter follows:
1741%
1742% o milliseconds: Specifies the number of milliseconds to delay before
1743% returning.
1744%
1745*/
1746MagickExport void MagickDelay(const MagickSizeType milliseconds)
1747{
1748 if (milliseconds == 0)
1749 return;
1750#if defined(MAGICKCORE_HAVE_NANOSLEEP)
1751 {
1752 struct timespec
1753 timer;
1754
1755 timer.tv_sec=(time_t) (milliseconds/1000);
1756 timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1757 (void) nanosleep(&timer,(struct timespec *) NULL);
1758 }
1759#elif defined(MAGICKCORE_HAVE_USLEEP)
1760 usleep(1000*milliseconds);
1761#elif defined(MAGICKCORE_HAVE_SELECT)
1762 {
1763 struct timeval
1764 timer;
1765
1766 timer.tv_sec=(long) milliseconds/1000;
1767 timer.tv_usec=(long) (milliseconds % 1000)*1000;
1768 (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1769 }
1770#elif defined(MAGICKCORE_HAVE_POLL)
1771 (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1772#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1773 Sleep((long) milliseconds);
1774#elif defined(vms)
1775 {
1776 float
1777 timer;
1778
1779 timer=milliseconds/1000.0;
1780 lib$wait(&timer);
1781 }
1782#elif defined(__BEOS__)
1783 snooze(1000*milliseconds);
1784#else
1785 {
1786 clock_t
1787 time_end;
1788
1789 time_end=clock()+milliseconds*CLOCKS_PER_SEC/1000;
1790 while (clock() < time_end)
1791 {
1792 }
1793 }
1794#endif
1795}
1796
1797/*
1798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1799% %
1800% %
1801% %
1802% M u l t i l i n e C e n s u s %
1803% %
1804% %
1805% %
1806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1807%
1808% MultilineCensus() returns the number of lines within a label. A line is
1809% represented by a \n character.
1810%
1811% The format of the MultilineCensus method is:
1812%
1813% size_t MultilineCensus(const char *label)
1814%
1815% A description of each parameter follows.
1816%
1817% o label: This character string is the label.
1818%
1819%
1820*/
1821MagickExport size_t MultilineCensus(const char *label)
1822{
1823 size_t
1824 number_lines;
1825
1826 /*
1827 Determine the number of lines within this label.
1828 */
1829 if (label == (char *) NULL)
1830 return(0);
1831 for (number_lines=1; *label != '\0'; label++)
1832 if (*label == '\n')
1833 number_lines++;
1834 return(number_lines);
1835}
1836
1837/*
1838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1839% %
1840% %
1841% %
1842% S h r e d F i l e %
1843% %
1844% %
1845% %
1846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1847%
1848% ShredFile() overwrites the specified file with random data. The overwrite
1849% is optional and is only required to help keep the contents of the file
1850% private.
1851%
1852% The format of the ShredFile method is:
1853%
1854% MagickBooleanType ShredFile(const char *path)
1855%
1856% A description of each parameter follows.
1857%
1858% o path: Specifies a path to a file.
1859%
1860*/
1861MagickPrivate MagickBooleanType ShredFile(const char *path)
1862{
1863 int
1864 file,
1865 status;
1866
1867 MagickSizeType
1868 length;
1869
1871 *random_info;
1872
1873 size_t
1874 quantum;
1875
1876 ssize_t
1877 i;
1878
1879 static ssize_t
1880 passes = -1;
1881
1883 *key;
1884
1885 struct stat
1886 file_stats;
1887
1888 if ((path == (const char *) NULL) || (*path == '\0'))
1889 return(MagickFalse);
1890 if (passes == -1)
1891 {
1892 char
1893 *property;
1894
1895 passes=0;
1896 property=GetEnvironmentValue("MAGICK_SHRED_PASSES");
1897 if (property != (char *) NULL)
1898 {
1899 passes=(ssize_t) StringToInteger(property);
1900 property=DestroyString(property);
1901 }
1902 property=GetPolicyValue("system:shred");
1903 if (property != (char *) NULL)
1904 {
1905 passes=(ssize_t) StringToInteger(property);
1906 property=DestroyString(property);
1907 }
1908 }
1909 if (passes == 0)
1910 return(MagickTrue);
1911 file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
1912 if (file == -1)
1913 return(MagickFalse);
1914 /*
1915 Shred the file.
1916 */
1917 quantum=(size_t) MagickMinBufferExtent;
1918 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1919 quantum=(size_t) MagickMin(file_stats.st_size,MagickMinBufferExtent);
1920 length=(MagickSizeType) file_stats.st_size;
1921 random_info=AcquireRandomInfo();
1922 key=GetRandomKey(random_info,quantum);
1923 for (i=0; i < passes; i++)
1924 {
1925 MagickOffsetType
1926 j;
1927
1928 ssize_t
1929 count;
1930
1931 if (lseek(file,0,SEEK_SET) < 0)
1932 break;
1933 for (j=0; j < (MagickOffsetType) length; j+=count)
1934 {
1935 if (i != 0)
1936 SetRandomKey(random_info,quantum,GetStringInfoDatum(key));
1937 count=write(file,GetStringInfoDatum(key),(size_t)
1938 MagickMin((MagickSizeType) quantum,length-j));
1939 if (count <= 0)
1940 {
1941 count=0;
1942 if (errno != EINTR)
1943 break;
1944 }
1945 }
1946 if (j < (MagickOffsetType) length)
1947 break;
1948 }
1949 key=DestroyStringInfo(key);
1950 random_info=DestroyRandomInfo(random_info);
1951 status=close(file);
1952 return((status == -1 || i < passes) ? MagickFalse : MagickTrue);
1953}
Definition mac.h:42
Definition mac.h:54