MagickCore  6.9.13-40
Convert, Edit, Or Compose Bitmap Images
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 */
77 static const char
78  Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
79 
80 /*
81  Forward declaration.
82 */
83 static 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 */
109 MagickExport 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 
151 MagickExport 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 */
279 MagickExport 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 */
344 MagickExport 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 */
500 MagickExport 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 */
584 MagickExport 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 */
616 MagickExport 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 */
747 static 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 
764 MagickExport 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 
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 */
1023 MagickExport 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 */
1162 MagickExport 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 */
1203 MagickExport 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 */
1251 MagickExport 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 */
1461 MagickExport 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 */
1524 MagickExport 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 */
1569 static 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)
1623 extern "C" {
1624 #endif
1625 
1626 static 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 
1641 MagickExport 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 */
1763 MagickExport 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 */
1838 MagickExport 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 */
1878 MagickPrivate 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:53
Definition: mac.h:41