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