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/license/ %
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 passes=GetPolicyValue("system:shred");
182 if (passes != (char *) NULL)
183 passes=DestroyString(passes);
184 else
185 {
186 (void) AcquireUniqueFilename(destination);
187 (void) RelinquishUniqueFileResource(destination);
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+=(ptrdiff_t) 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*/
747static inline void getcwd_utf8(char *path,size_t extent)
748{
749#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
750 char
751 *directory;
752
753 directory=getcwd(path,extent);
754 (void) directory;
755#else
756 wchar_t
757 wide_path[MaxTextExtent];
758
759 (void) _wgetcwd(wide_path,MaxTextExtent-1);
760 (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
761#endif
762}
763
764MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
765 char ***arguments)
766{
767 char
768 home_directory[MaxTextExtent],
769 **vector;
770
771 ssize_t
772 i,
773 j;
774
775 size_t
776 number_files;
777
778 ssize_t
779 count,
780 parameters;
781
782 /*
783 Allocate argument vector.
784 */
785 assert(number_arguments != (int *) NULL);
786 assert(arguments != (char ***) NULL);
787 if (IsEventLogging() != MagickFalse)
788 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
789 vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
790 sizeof(*vector));
791 if (vector == (char **) NULL)
792 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
793 /*
794 Expand any wildcard filenames.
795 */
796 *home_directory='\0';
797 count=0;
798 for (i=0; i < (ssize_t) *number_arguments; i++)
799 {
800 char
801 **filelist,
802 filename[MaxTextExtent],
803 magick[MaxTextExtent],
804 *option,
805 path[MaxTextExtent],
806 subimage[MaxTextExtent];
807
808 MagickBooleanType
809 destroy;
810
811 option=(*arguments)[i];
812 *magick='\0';
813 *path='\0';
814 *filename='\0';
815 *subimage='\0';
816 number_files=0;
817 vector[count++]=ConstantString(option);
818 destroy=MagickTrue;
819 parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
820 if (parameters > 0)
821 {
822 /*
823 Do not expand command option parameters.
824 */
825 for (j=0; j < parameters; j++)
826 {
827 i++;
828 if (i == (ssize_t) *number_arguments)
829 break;
830 option=(*arguments)[i];
831 vector[count++]=ConstantString(option);
832 }
833 continue;
834 }
835 if ((*option == '"') || (*option == '\''))
836 continue;
837 GetPathComponent(option,TailPath,filename);
838 GetPathComponent(option,MagickPath,magick);
839 if ((LocaleCompare(magick,"CAPTION") == 0) ||
840 (LocaleCompare(magick,"LABEL") == 0) ||
841 (LocaleCompare(magick,"PANGO") == 0) ||
842 (LocaleCompare(magick,"VID") == 0))
843 continue;
844 if ((IsGlob(filename) == MagickFalse) && (*option != '@'))
845 continue;
846 if (IsPathAccessible(option) != MagickFalse)
847 continue;
848 if (*option != '@')
849 {
850 /*
851 Generate file list from wildcard filename (e.g. *.jpg).
852 */
853 GetPathComponent(option,HeadPath,path);
854 GetPathComponent(option,SubimagePath,subimage);
855 ExpandFilename(path);
856 if (*home_directory == '\0')
857 getcwd_utf8(home_directory,MaxTextExtent-1);
858 filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
859 &number_files);
860 }
861 else
862 {
863 char
864 *files;
865
866 ExceptionInfo
867 *exception;
868
869 int
870 length;
871
872 /*
873 Generate file list from file list (e.g. @filelist.txt).
874 */
875 exception=AcquireExceptionInfo();
876 files=FileToString(option,~0UL,exception);
877 exception=DestroyExceptionInfo(exception);
878 if (files == (char *) NULL)
879 continue;
880 filelist=StringToArgv(files,&length);
881 if (filelist == (char **) NULL)
882 continue;
883 files=DestroyString(files);
884 filelist[0]=DestroyString(filelist[0]);
885 for (j=0; j < (ssize_t) (length-1); j++)
886 filelist[j]=filelist[j+1];
887 number_files=(size_t) length-1;
888 }
889 if (filelist == (char **) NULL)
890 continue;
891 for (j=0; j < (ssize_t) number_files; j++)
892 if (IsPathDirectory(filelist[j]) <= 0)
893 break;
894 if (j == (ssize_t) number_files)
895 {
896 for (j=0; j < (ssize_t) number_files; j++)
897 filelist[j]=DestroyString(filelist[j]);
898 filelist=(char **) RelinquishMagickMemory(filelist);
899 continue;
900 }
901 /*
902 Transfer file list to argument vector.
903 */
904 vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
905 count+number_files+1,sizeof(*vector));
906 if (vector == (char **) NULL)
907 {
908 for (j=0; j < (ssize_t) number_files; j++)
909 filelist[j]=DestroyString(filelist[j]);
910 filelist=(char **) RelinquishMagickMemory(filelist);
911 return(MagickFalse);
912 }
913 for (j=0; j < (ssize_t) number_files; j++)
914 {
915 option=filelist[j];
916 parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
917 if (parameters > 0)
918 {
919 ssize_t
920 k;
921
922 /*
923 Do not expand command option parameters.
924 */
925 vector[count++]=ConstantString(option);
926 for (k=0; k < parameters; k++)
927 {
928 j++;
929 if (j == (ssize_t) number_files)
930 break;
931 option=filelist[j];
932 vector[count++]=ConstantString(option);
933 }
934 continue;
935 }
936 (void) CopyMagickString(filename,path,MaxTextExtent);
937 if (*path != '\0')
938 (void) ConcatenateMagickString(filename,DirectorySeparator,
939 MaxTextExtent);
940 if (filelist[j] != (char *) NULL)
941 (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
942 filelist[j]=DestroyString(filelist[j]);
943 if (strlen(filename) >= (MaxTextExtent-1))
944 ThrowFatalException(OptionFatalError,"FilenameTruncated");
945 if (IsPathDirectory(filename) <= 0)
946 {
947 char
948 path[MaxTextExtent];
949
950 *path='\0';
951 if (*magick != '\0')
952 {
953 (void) ConcatenateMagickString(path,magick,MaxTextExtent);
954 (void) ConcatenateMagickString(path,":",MaxTextExtent);
955 }
956 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
957 if (*subimage != '\0')
958 {
959 (void) ConcatenateMagickString(path,"[",MaxTextExtent);
960 (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
961 (void) ConcatenateMagickString(path,"]",MaxTextExtent);
962 }
963 if (strlen(path) >= (MaxTextExtent-1))
964 ThrowFatalException(OptionFatalError,"FilenameTruncated");
965 if (destroy != MagickFalse)
966 {
967 count--;
968 vector[count]=DestroyString(vector[count]);
969 destroy=MagickFalse;
970 }
971 vector[count++]=ConstantString(path);
972 }
973 }
974 filelist=(char **) RelinquishMagickMemory(filelist);
975 }
976 vector[count]=(char *) NULL;
977 if (IsEventLogging() != MagickFalse)
978 {
979 char
980 *command_line;
981
982 command_line=AcquireString(vector[0]);
983 for (i=1; i < count; i++)
984 {
985 (void) ConcatenateString(&command_line," {");
986 (void) ConcatenateString(&command_line,vector[i]);
987 (void) ConcatenateString(&command_line,"}");
988 }
989 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
990 "Command line: %s",command_line);
991 command_line=DestroyString(command_line);
992 }
993 *number_arguments=(int) count;
994 *arguments=vector;
995 return(MagickTrue);
996}
997
998/*
999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000% %
1001% %
1002% %
1003% G e t E x e c u t i o n P a t h %
1004% %
1005% %
1006% %
1007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008%
1009% GetExecutionPath() returns the pathname of the executable that started
1010% the process. On success MagickTrue is returned, otherwise MagickFalse.
1011%
1012% The format of the GetExecutionPath method is:
1013%
1014% MagickBooleanType GetExecutionPath(char *path,const size_t extent)
1015%
1016% A description of each parameter follows:
1017%
1018% o path: the pathname of the executable that started the process.
1019%
1020% o extent: the maximum extent of the path.
1021%
1022*/
1023MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
1024{
1025 char
1026 *directory;
1027
1028 *path='\0';
1029 directory=getcwd(path,(unsigned long) extent);
1030 (void) directory;
1031#if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
1032 {
1033 char
1034 link_path[MaxTextExtent],
1035 execution_path[PATH_MAX+1];
1036
1037 ssize_t
1038 count;
1039
1040 (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe",
1041 (double) getpid());
1042 count=readlink(link_path,execution_path,PATH_MAX);
1043 if (count == -1)
1044 {
1045 (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file",
1046 (double) getpid());
1047 count=readlink(link_path,execution_path,PATH_MAX);
1048 }
1049 if ((count > 0) && (count <= (ssize_t) PATH_MAX))
1050 {
1051 execution_path[count]='\0';
1052 (void) CopyMagickString(path,execution_path,extent);
1053 }
1054 }
1055#endif
1056#if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
1057 {
1058 char
1059 executable_path[PATH_MAX << 1];
1060
1061 uint32_t
1062 length;
1063
1064 length=sizeof(executable_path);
1065 if (_NSGetExecutablePath(executable_path,&length) == 0)
1066 {
1067 char
1068 *real_path = realpath_utf8(executable_path);
1069
1070 if (real_path != (char *) NULL)
1071 {
1072 (void) CopyMagickString(path,real_path,extent);
1073 real_path=DestroyString(real_path);
1074 }
1075 }
1076 }
1077#endif
1078#if defined(MAGICKCORE_HAVE_GETEXECNAME)
1079 {
1080 const char
1081 *execution_path;
1082
1083 execution_path=(const char *) getexecname();
1084 if (execution_path != (const char *) NULL)
1085 {
1086 if (*execution_path != *DirectorySeparator)
1087 (void) ConcatenateMagickString(path,DirectorySeparator,extent);
1088 (void) ConcatenateMagickString(path,execution_path,extent);
1089 }
1090 }
1091#endif
1092#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1093 NTGetExecutionPath(path,extent);
1094#endif
1095#if defined(__GNU__)
1096 {
1097 char
1098 *program_name;
1099
1100 ssize_t
1101 count;
1102
1103 count=0;
1104 program_name=program_invocation_name;
1105 if (*program_invocation_name != '/')
1106 {
1107 size_t
1108 extent;
1109
1110 extent=strlen(directory)+strlen(program_name)+2;
1111 program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1112 if (program_name == (char *) NULL)
1113 program_name=program_invocation_name;
1114 else
1115 count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1116 program_invocation_name);
1117 }
1118 if (count != -1)
1119 {
1120 char
1121 *real_path = realpath_utf8(program_name);
1122
1123 if (real_path != (char *) NULL)
1124 {
1125 (void) CopyMagickString(path,real_path,extent);
1126 real_path=DestroyString(real_path);
1127 }
1128 }
1129 if (program_name != program_invocation_name)
1130 program_name=(char *) RelinquishMagickMemory(program_name);
1131 }
1132#endif
1133#if defined(__OpenBSD__)
1134 {
1135 extern char
1136 *__progname;
1137
1138 (void) CopyMagickString(path,__progname,extent);
1139 }
1140#endif
1141 return(IsPathAccessible(path));
1142}
1143
1144/*
1145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1146% %
1147% %
1148% %
1149% G e t M a g i c k P a g e S i z e %
1150% %
1151% %
1152% %
1153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154%
1155% GetMagickPageSize() returns the memory page size.
1156%
1157% The format of the GetMagickPageSize method is:
1158%
1159% ssize_t GetMagickPageSize()
1160%
1161*/
1162MagickExport ssize_t GetMagickPageSize(void)
1163{
1164 static ssize_t
1165 page_size = -1;
1166
1167 if (page_size > 0)
1168 return(page_size);
1169#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1170 page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1171#elif defined(MAGICKCORE_HAVE_GETPAGESIZE)
1172 page_size=(ssize_t) getpagesize();
1173#endif
1174 if (page_size <= 0)
1175 page_size=4096;
1176 return(page_size);
1177}
1178
1179/*
1180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1181% %
1182% %
1183% %
1184% G e t P a t h A t t r i b u t e s %
1185% %
1186% %
1187% %
1188%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189%
1190% GetPathAttributes() returns attributes (e.g. size of file) about a path.
1191%
1192% The path of the GetPathAttributes method is:
1193%
1194% MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1195%
1196% A description of each parameter follows.
1197%
1198% o path: the file path.
1199%
1200% o attributes: the path attributes are returned here.
1201%
1202*/
1203MagickExport MagickBooleanType GetPathAttributes(const char *path,
1204 void *attributes)
1205{
1206 MagickBooleanType
1207 status;
1208
1209 if (path == (const char *) NULL)
1210 {
1211 errno=EINVAL;
1212 return(MagickFalse);
1213 }
1214 (void) memset(attributes,0,sizeof(struct stat));
1215 status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
1216 MagickFalse;
1217 return(status);
1218}
1219
1220/*
1221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222% %
1223% %
1224% %
1225% G e t P a t h C o m p o n e n t %
1226% %
1227% %
1228% %
1229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1230%
1231% GetPathComponent() returns the parent directory name, filename, basename, or
1232% extension of a file path.
1233%
1234% The component string pointed to must have at least MaxTextExtent space
1235% for the results to be stored.
1236%
1237% The format of the GetPathComponent function is:
1238%
1239% GetPathComponent(const char *path,PathType type,char *component)
1240%
1241% A description of each parameter follows:
1242%
1243% o path: Specifies a pointer to a character array that contains the
1244% file path.
1245%
1246% o type: Specifies which file path component to return.
1247%
1248% o component: the selected file path component is returned here.
1249%
1250*/
1251MagickExport void GetPathComponent(const char *path,PathType type,
1252 char *component)
1253{
1254 char
1255 *q;
1256
1257 char
1258 *p;
1259
1260 size_t
1261 magick_length,
1262 subimage_offset,
1263 subimage_length;
1264
1265 assert(path != (const char *) NULL);
1266 assert(component != (char *) NULL);
1267 if (IsEventLogging() != MagickFalse)
1268 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1269 if (*path == '\0')
1270 {
1271 *component='\0';
1272 return;
1273 }
1274 (void) CopyMagickString(component,path,MagickPathExtent);
1275 subimage_length=0;
1276 subimage_offset=0;
1277 if (type != SubcanonicalPath)
1278 {
1279 p=component+strlen(component)-1;
1280 if ((strlen(component) > 2) && (*p == ']'))
1281 {
1282 q=strrchr(component,'[');
1283 if ((q != (char *) NULL) && ((q == component) || (*(q-1) != ']')) &&
1284 (IsPathAccessible(path) == MagickFalse))
1285 {
1286 /*
1287 Look for scene specification (e.g. img0001.pcd[4]).
1288 */
1289 *p='\0';
1290 if ((IsSceneGeometry(q+1,MagickFalse) == MagickFalse) &&
1291 (IsGeometry(q+1) == MagickFalse))
1292 *p=']';
1293 else
1294 {
1295 subimage_length=(size_t) (p-q);
1296 subimage_offset=(size_t) (q-component+1);
1297 *q='\0';
1298 }
1299 }
1300 }
1301 }
1302 magick_length=0;
1303#if defined(__OS2__)
1304 if (path[1] != ":")
1305#endif
1306 for (p=component; *p != '\0'; p++)
1307 {
1308 if ((*p == '%') && (*(p+1) == '['))
1309 {
1310 /*
1311 Skip over %[...].
1312 */
1313 for (p++; (*p != ']') && (*p != '\0'); p++) ;
1314 if (*p == '\0')
1315 break;
1316 }
1317 if ((p != component) && (*p == ':') && (IsPathDirectory(component) < 0) &&
1318 (IsPathAccessible(component) == MagickFalse))
1319 {
1320 /*
1321 Look for image format specification (e.g. ps3:image).
1322 */
1323 *p='\0';
1324 if (IsMagickConflict(component) != MagickFalse)
1325 *p=':';
1326 else
1327 {
1328 magick_length=(size_t) (p-component+1);
1329 for (q=component; *(++p) != '\0'; q++)
1330 *q=(*p);
1331 *q='\0';
1332 }
1333 break;
1334 }
1335 }
1336 p=component;
1337 if (*p != '\0')
1338 for (p=component+strlen(component)-1; p > component; p--)
1339 if (IsBasenameSeparator(*p) != MagickFalse)
1340 break;
1341 switch (type)
1342 {
1343 case MagickPath:
1344 {
1345 if (magick_length != 0)
1346 (void) CopyMagickString(component,path,magick_length);
1347 else
1348 *component='\0';
1349 break;
1350 }
1351 case RootPath:
1352 {
1353 if (*component != '\0')
1354 {
1355 for (p=component+(strlen(component)-1); p > component; p--)
1356 {
1357 if (IsBasenameSeparator(*p) != MagickFalse)
1358 break;
1359 if (*p == '.')
1360 break;
1361 }
1362 if (*p == '.')
1363 *p='\0';
1364 break;
1365 }
1366 magick_fallthrough;
1367 }
1368 case HeadPath:
1369 {
1370 *p='\0';
1371 break;
1372 }
1373 case TailPath:
1374 {
1375 if (IsBasenameSeparator(*p) != MagickFalse)
1376 (void) CopyMagickString(component,p+1,MagickPathExtent);
1377 break;
1378 }
1379 case BasePath:
1380 {
1381 if (IsBasenameSeparator(*p) != MagickFalse)
1382 (void) CopyMagickString(component,p+1,MagickPathExtent);
1383 if (*component != '\0')
1384 for (p=component+(strlen(component)-1); p > component; p--)
1385 if (*p == '.')
1386 {
1387 *p='\0';
1388 break;
1389 }
1390 break;
1391 }
1392 case BasePathSansCompressExtension:
1393 {
1394 char
1395 extension[MagickPathExtent];
1396
1397 /*
1398 Base path sans any compression extension.
1399 */
1400 GetPathComponent(path,ExtensionPath,extension);
1401 if ((LocaleCompare(extension,"bz2") == 0) ||
1402 (LocaleCompare(extension,"gz") == 0) ||
1403 (LocaleCompare(extension,"svgz") == 0) ||
1404 (LocaleCompare(extension,"wmz") == 0) ||
1405 (LocaleCompare(extension,"Z") == 0))
1406 GetPathComponent(path,BasePath,component);
1407 break;
1408 }
1409 case ExtensionPath:
1410 {
1411 if (IsBasenameSeparator(*p) != MagickFalse)
1412 (void) CopyMagickString(component,p+1,MagickPathExtent);
1413 if (*component != '\0')
1414 for (p=component+strlen(component)-1; p > component; p--)
1415 if (*p == '.')
1416 break;
1417 *component='\0';
1418 if (*p == '.')
1419 (void) CopyMagickString(component,p+1,MagickPathExtent);
1420 break;
1421 }
1422 case SubimagePath:
1423 {
1424 *component='\0';
1425 if ((subimage_length != 0) && (magick_length < subimage_offset))
1426 (void) CopyMagickString(component,path+subimage_offset,subimage_length);
1427 break;
1428 }
1429 case SubcanonicalPath:
1430 case CanonicalPath:
1431 case UndefinedPath:
1432 break;
1433 }
1434}
1435
1436/*
1437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438% %
1439% %
1440% %
1441% G e t P a t h C o m p o n e n t s %
1442% %
1443% %
1444% %
1445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446%
1447% GetPathComponents() returns a list of path components.
1448%
1449% The format of the GetPathComponents method is:
1450%
1451% char **GetPathComponents(const char *path,
1452% size_t *number_components)
1453%
1454% A description of each parameter follows:
1455%
1456% o path: Specifies the string to segment into a list.
1457%
1458% o number_components: return the number of components in the list
1459%
1460*/
1461MagickExport char **GetPathComponents(const char *path,
1462 size_t *number_components)
1463{
1464 char
1465 **components;
1466
1467 const char
1468 *p,
1469 *q;
1470
1471 ssize_t
1472 i;
1473
1474 if (path == (char *) NULL)
1475 return((char **) NULL);
1476 *number_components=1;
1477 for (p=path; *p != '\0'; p++)
1478 if (IsBasenameSeparator(*p))
1479 (*number_components)++;
1480 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1481 sizeof(*components));
1482 if (components == (char **) NULL)
1483 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1484 p=path;
1485 for (i=0; i < (ssize_t) *number_components; i++)
1486 {
1487 for (q=p; *q != '\0'; q++)
1488 if (IsBasenameSeparator(*q))
1489 break;
1490 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1491 sizeof(**components));
1492 if (components[i] == (char *) NULL)
1493 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1494 (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1495 p=q+1;
1496 }
1497 components[i]=(char *) NULL;
1498 return(components);
1499}
1500
1501/*
1502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1503% %
1504% %
1505% %
1506% I s P a t h A c c e s s i b l e %
1507% %
1508% %
1509% %
1510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1511%
1512% IsPathAccessible() returns MagickTrue if the file as defined by the path is
1513% accessible.
1514%
1515% The format of the IsPathAccessible method is:
1516%
1517% MagickBooleanType IsPathAccessible(const char *path)
1518%
1519% A description of each parameter follows.
1520%
1521% o path: Specifies a path to a file.
1522%
1523*/
1524MagickExport MagickBooleanType IsPathAccessible(const char *path)
1525{
1526 MagickBooleanType
1527 status;
1528
1529 struct stat
1530 attributes;
1531
1532 if ((path == (const char *) NULL) || (*path == '\0'))
1533 return(MagickFalse);
1534 if (LocaleCompare(path,"-") == 0)
1535 return(MagickTrue);
1536 status=GetPathAttributes(path,&attributes);
1537 if (status == MagickFalse)
1538 return(status);
1539 if (S_ISREG(attributes.st_mode) == 0)
1540 return(MagickFalse);
1541 if (access_utf8(path,F_OK) != 0)
1542 return(MagickFalse);
1543 return(MagickTrue);
1544}
1545
1546/*
1547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548% %
1549% %
1550% %
1551+ I s P a t h D i r e c t o r y %
1552% %
1553% %
1554% %
1555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556%
1557% IsPathDirectory() returns -1 if the directory does not exist, 1 is returned
1558% if the path represents a directory otherwise 0.
1559%
1560% The format of the IsPathDirectory method is:
1561%
1562% int IsPathDirectory(const char *path)
1563%
1564% A description of each parameter follows.
1565%
1566% o path: The directory path.
1567%
1568*/
1569static int IsPathDirectory(const char *path)
1570{
1571 MagickBooleanType
1572 status;
1573
1574 struct stat
1575 attributes;
1576
1577 if ((path == (const char *) NULL) || (*path == '\0'))
1578 return(MagickFalse);
1579 status=GetPathAttributes(path,&attributes);
1580 if (status == MagickFalse)
1581 return(-1);
1582 if (S_ISDIR(attributes.st_mode) == 0)
1583 return(0);
1584 return(1);
1585}
1586
1587/*
1588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1589% %
1590% %
1591% %
1592% L i s t F i l e s %
1593% %
1594% %
1595% %
1596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597%
1598% ListFiles() reads the directory specified and returns a list of filenames
1599% contained in the directory sorted in ascending alphabetic order.
1600%
1601% The format of the ListFiles function is:
1602%
1603% char **ListFiles(const char *directory,const char *pattern,
1604% ssize_t *number_entries)
1605%
1606% A description of each parameter follows:
1607%
1608% o filelist: Method ListFiles returns a list of filenames contained
1609% in the directory. If the directory specified cannot be read or it is
1610% a file a NULL list is returned.
1611%
1612% o directory: Specifies a pointer to a text string containing a directory
1613% name.
1614%
1615% o pattern: Specifies a pointer to a text string containing a pattern.
1616%
1617% o number_entries: This integer returns the number of filenames in the
1618% list.
1619%
1620*/
1621
1622#if defined(__cplusplus) || defined(c_plusplus)
1623extern "C" {
1624#endif
1625
1626static int FileCompare(const void *x,const void *y)
1627{
1628 const char
1629 **p,
1630 **q;
1631
1632 p=(const char **) x;
1633 q=(const char **) y;
1634 return(LocaleCompare(*p,*q));
1635}
1636
1637#if defined(__cplusplus) || defined(c_plusplus)
1638}
1639#endif
1640
1641MagickExport char **ListFiles(const char *directory,const char *pattern,
1642 size_t *number_entries)
1643{
1644 char
1645 **filelist;
1646
1647 DIR
1648 *current_directory;
1649
1650 struct dirent
1651 *buffer,
1652 *entry;
1653
1654 size_t
1655 max_entries;
1656
1657 /*
1658 Open directory.
1659 */
1660 assert(directory != (const char *) NULL);
1661 assert(pattern != (const char *) NULL);
1662 assert(number_entries != (size_t *) NULL);
1663 if (IsEventLogging() != MagickFalse)
1664 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1665 *number_entries=0;
1666 current_directory=opendir(directory);
1667 if (current_directory == (DIR *) NULL)
1668 return((char **) NULL);
1669 /*
1670 Allocate filelist.
1671 */
1672 max_entries=2048;
1673 filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1674 sizeof(*filelist));
1675 if (filelist == (char **) NULL)
1676 {
1677 (void) closedir(current_directory);
1678 return((char **) NULL);
1679 }
1680 /*
1681 Save the current and change to the new directory.
1682 */
1683 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
1684 if (buffer == (struct dirent *) NULL)
1685 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1686 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1687 (entry != (struct dirent *) NULL))
1688 {
1689 if ((LocaleCompare(entry->d_name,".") == 0) ||
1690 (LocaleCompare(entry->d_name,"..") == 0))
1691 continue;
1692 if ((IsPathDirectory(entry->d_name) > 0) ||
1693#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1694 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1695#else
1696 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1697#endif
1698 {
1699 if (*number_entries >= max_entries)
1700 {
1701 /*
1702 Extend the file list.
1703 */
1704 max_entries<<=1;
1705 filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1706 max_entries,sizeof(*filelist));
1707 if (filelist == (char **) NULL)
1708 break;
1709 }
1710#if defined(vms)
1711 {
1712 char
1713 *p;
1714
1715 p=strchr(entry->d_name,';');
1716 if (p)
1717 *p='\0';
1718 if (*number_entries > 0)
1719 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1720 continue;
1721 }
1722#endif
1723 filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1724 (*number_entries)++;
1725 }
1726 }
1727 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1728 (void) closedir(current_directory);
1729 if (filelist == (char **) NULL)
1730 return((char **) NULL);
1731 /*
1732 Sort filelist in ascending order.
1733 */
1734 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1735 FileCompare);
1736 return(filelist);
1737}
1738
1739/*
1740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1741% %
1742% %
1743% %
1744% M a g i c k D e l a y %
1745% %
1746% %
1747% %
1748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1749%
1750% MagickDelay() suspends program execution for the number of milliseconds
1751% specified.
1752%
1753% The format of the Delay method is:
1754%
1755% void MagickDelay(const MagickSizeType milliseconds)
1756%
1757% A description of each parameter follows:
1758%
1759% o milliseconds: Specifies the number of milliseconds to delay before
1760% returning.
1761%
1762*/
1763MagickExport void MagickDelay(const MagickSizeType milliseconds)
1764{
1765 if (milliseconds == 0)
1766 return;
1767#if defined(MAGICKCORE_HAVE_NANOSLEEP)
1768 {
1769 struct timespec
1770 timer;
1771
1772 timer.tv_sec=(time_t) (milliseconds/1000);
1773 timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1774 (void) nanosleep(&timer,(struct timespec *) NULL);
1775 }
1776#elif defined(MAGICKCORE_HAVE_USLEEP)
1777 usleep(1000*milliseconds);
1778#elif defined(MAGICKCORE_HAVE_SELECT)
1779 {
1780 struct timeval
1781 timer;
1782
1783 timer.tv_sec=(long) milliseconds/1000;
1784 timer.tv_usec=(long) (milliseconds % 1000)*1000;
1785 (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1786 }
1787#elif defined(MAGICKCORE_HAVE_POLL)
1788 (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1789#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1790 Sleep((long) milliseconds);
1791#elif defined(vms)
1792 {
1793 float
1794 timer;
1795
1796 timer=milliseconds/1000.0;
1797 lib$wait(&timer);
1798 }
1799#elif defined(__BEOS__)
1800 snooze(1000*milliseconds);
1801#else
1802 {
1803 clock_t
1804 time_end;
1805
1806 time_end=clock()+milliseconds*CLOCKS_PER_SEC/1000;
1807 while (clock() < time_end)
1808 {
1809 }
1810 }
1811#endif
1812}
1813
1814/*
1815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1816% %
1817% %
1818% %
1819% M u l t i l i n e C e n s u s %
1820% %
1821% %
1822% %
1823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1824%
1825% MultilineCensus() returns the number of lines within a label. A line is
1826% represented by a \n character.
1827%
1828% The format of the MultilineCensus method is:
1829%
1830% size_t MultilineCensus(const char *label)
1831%
1832% A description of each parameter follows.
1833%
1834% o label: This character string is the label.
1835%
1836%
1837*/
1838MagickExport size_t MultilineCensus(const char *label)
1839{
1840 size_t
1841 number_lines;
1842
1843 /*
1844 Determine the number of lines within this label.
1845 */
1846 if (label == (char *) NULL)
1847 return(0);
1848 for (number_lines=1; *label != '\0'; label++)
1849 if (*label == '\n')
1850 number_lines++;
1851 return(number_lines);
1852}
1853
1854/*
1855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1856% %
1857% %
1858% %
1859% S h r e d F i l e %
1860% %
1861% %
1862% %
1863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864%
1865% ShredFile() overwrites the specified file with random data. The overwrite
1866% is optional and is only required to help keep the contents of the file
1867% private.
1868%
1869% The format of the ShredFile method is:
1870%
1871% MagickBooleanType ShredFile(const char *path)
1872%
1873% A description of each parameter follows.
1874%
1875% o path: Specifies a path to a file.
1876%
1877*/
1878MagickPrivate MagickBooleanType ShredFile(const char *path)
1879{
1880 int
1881 file,
1882 status;
1883
1884 MagickSizeType
1885 length;
1886
1887 RandomInfo
1888 *random_info;
1889
1890 size_t
1891 quantum;
1892
1893 ssize_t
1894 i;
1895
1896 static ssize_t
1897 passes = -1;
1898
1899 StringInfo
1900 *key;
1901
1902 struct stat
1903 file_stats;
1904
1905 if ((path == (const char *) NULL) || (*path == '\0'))
1906 return(MagickFalse);
1907 if (passes == -1)
1908 {
1909 char
1910 *property;
1911
1912 passes=0;
1913 property=GetEnvironmentValue("MAGICK_SHRED_PASSES");
1914 if (property != (char *) NULL)
1915 {
1916 passes=(ssize_t) StringToInteger(property);
1917 property=DestroyString(property);
1918 }
1919 property=GetPolicyValue("system:shred");
1920 if (property != (char *) NULL)
1921 {
1922 passes=(ssize_t) StringToInteger(property);
1923 property=DestroyString(property);
1924 }
1925 }
1926 if (passes == 0)
1927 return(MagickTrue);
1928 file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
1929 if (file == -1)
1930 return(MagickFalse);
1931 /*
1932 Shred the file.
1933 */
1934 quantum=(size_t) MagickMinBufferExtent;
1935 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1936 quantum=(size_t) MagickMin(file_stats.st_size,MagickMinBufferExtent);
1937 length=(MagickSizeType) file_stats.st_size;
1938 random_info=AcquireRandomInfo();
1939 key=GetRandomKey(random_info,quantum);
1940 for (i=0; i < passes; i++)
1941 {
1942 MagickOffsetType
1943 j;
1944
1945 ssize_t
1946 count;
1947
1948 if (lseek(file,0,SEEK_SET) < 0)
1949 break;
1950 for (j=0; j < (MagickOffsetType) length; j+=count)
1951 {
1952 if (i != 0)
1953 SetRandomKey(random_info,quantum,GetStringInfoDatum(key));
1954 count=write(file,GetStringInfoDatum(key),(size_t)
1955 MagickMin((MagickSizeType) quantum,length-j));
1956 if (count <= 0)
1957 {
1958 count=0;
1959 if (errno != EINTR)
1960 break;
1961 }
1962 }
1963 if (j < (MagickOffsetType) length)
1964 break;
1965 }
1966 key=DestroyStringInfo(key);
1967 random_info=DestroyRandomInfo(random_info);
1968 status=close(file);
1969 return((status == -1 || i < passes) ? MagickFalse : MagickTrue);
1970}
Definition mac.h:54