root/WizardsToolkit/trunk/utilities/utility.c

Revision 1, 16.4 KB (checked in by cristy, 3 months ago)


Line 
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%                     Wizard's Toolkit Utility Methods                        %
14%                                                                             %
15%                             Software Design                                 %
16%                               John Cristy                                   %
17%                               March 2003                                    %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2009 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%    http://www.wizards-toolkit.org/script/license.php                        %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <time.h>
46#include "wizard/studio.h"
47#include "wizard/WizardsToolkit.h"
48#include "wizard/exception-private.h"
49#include "utility_.h"
50
51/*
52  Forward declaration.
53*/
54static char
55   **ListFiles(const char *,const char *,unsigned long *);
56
57static int
58  IsDirectory(const char *);
59
60/*
61%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62%                                                                             %
63%                                                                             %
64%                                                                             %
65+   E x p a n d F i l e n a m e                                               %
66%                                                                             %
67%                                                                             %
68%                                                                             %
69%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70%
71%  ExpandFilename() expands '~' in a path.
72%
73%  The format of the ExpandFilename function is:
74%
75%      ExpandFilename(char *path)
76%
77%  A description of each parameter follows:
78%
79%    o path: Specifies a pointer to a character array that contains the
80%      path.
81%
82*/
83static void ExpandFilename(char *path)
84{
85  char
86    expand_path[MaxTextExtent];
87
88  if (path == (char *) NULL)
89    return;
90  if (*path != '~')
91    return;
92  (void) CopyWizardString(expand_path,path,MaxTextExtent);
93  if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
94    {
95      char
96        *home;
97
98      /*
99        Substitute ~ with $HOME.
100      */
101      (void) CopyWizardString(expand_path,".",MaxTextExtent);
102      (void) ConcatenateWizardString(expand_path,path+1,MaxTextExtent);
103      home=GetEnvironmentValue("HOME");
104      if (home == (char *) NULL)
105        home=GetEnvironmentValue("USERPROFILE");
106      if (home != (char *) NULL)
107        {
108          (void) CopyWizardString(expand_path,home,MaxTextExtent);
109          (void) ConcatenateWizardString(expand_path,path+1,MaxTextExtent);
110          home=DestroyString(home);
111        }
112    }
113  else
114    {
115#if defined(WIZARDSTOOLKIT_POSIX_SUPPORT)
116      char
117        username[MaxTextExtent];
118
119      register char
120        *p;
121
122      struct passwd
123        *entry;
124
125      /*
126        Substitute ~ with home directory from password file.
127      */
128      (void) CopyWizardString(username,path+1,MaxTextExtent);
129      p=strchr(username,'/');
130      if (p != (char *) NULL)
131        *p='\0';
132      entry=getpwnam(username);
133      if (entry == (struct passwd *) NULL)
134        return;
135      (void) CopyWizardString(expand_path,entry->pw_dir,MaxTextExtent);
136      if (p != (char *) NULL)
137        {
138          (void) ConcatenateWizardString(expand_path,"/",MaxTextExtent);
139          (void) ConcatenateWizardString(expand_path,p+1,MaxTextExtent);
140        }
141#endif
142    }
143  (void) CopyWizardString(path,expand_path,MaxTextExtent);
144}
145
146/*
147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148%                                                                             %
149%                                                                             %
150%                                                                             %
151%   E x p a n d F i l e n a m e s                                             %
152%                                                                             %
153%                                                                             %
154%                                                                             %
155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156%
157%  ExpandFilenames() checks each argument of the command line vector and
158%  expands it if they have a wildcard character.  For example, *.jpg might
159%  expand to:  bird.jpg rose.jpg tiki.jpg.
160%
161%  The format of the ExpandFilenames function is:
162%
163%      WizardBooleanType ExpandFilenames(int *argc,char ***argv)
164%
165%  A description of each parameter follows:
166%
167%    o argc: Specifies a pointer to an integer describing the number of
168%      elements in the argument vector.
169%
170%    o argv: Specifies a pointer to a text array containing the command line
171%      arguments.
172%
173*/
174WizardExport WizardBooleanType ExpandFilenames(int *argc,char ***argv)
175{
176  char
177    **filelist,
178    filename[MaxTextExtent],
179    home_directory[MaxTextExtent],
180    *option,
181    path[MaxTextExtent],
182    **vector;
183
184  long
185    count,
186    parameters;
187
188  register long
189    i,
190    j;
191
192  unsigned long
193    number_files;
194
195  /*
196    Allocate argument vector.
197  */
198  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
199  assert(argc != (int *) NULL);
200  assert(argv != (char ***) NULL);
201  vector=(char **) AcquireQuantumMemory(*argc+1UL,sizeof(*vector));
202  if (vector == (char **) NULL)
203    return(WizardFalse);
204  /*
205    Expand any wildcard filenames.
206  */
207  if (getcwd(home_directory,MaxTextExtent) == (char *) NULL)
208    return(WizardFalse);
209  count=0;
210  for (i=0; i < (long) *argc; i++)
211  {
212    option=(*argv)[i];
213    vector[count++]=ConstantString(option);
214    parameters=ParseWizardOption(WizardCommandOptions,WizardFalse,option);
215    if (parameters > 0)
216      {
217        /*
218          Do not expand command option parameters.
219        */
220        for (j=0; j < parameters; j++)
221        {
222          i++;
223          if (i == (long) *argc)
224            break;
225          option=(*argv)[i];
226          vector[count++]=ConstantString(option);
227        }
228        continue;
229      }
230    if ((*option == '"') || (*option == '\''))
231      continue;
232    GetPathComponent(option,TailPath,filename);
233    if (IsGlob(filename) == WizardFalse)
234      continue;
235    GetPathComponent(option,HeadPath,path);
236    ExpandFilename(path);
237    filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
238      &number_files);
239    if (filelist == (char **) NULL)
240      continue;
241    for (j=0; j < (long) number_files; j++)
242      if (IsDirectory(filelist[j]) <= 0)
243        break;
244    if (j == (long) number_files)
245      {
246        for (j=0; j < (long) number_files; j++)
247          filelist[j]=DestroyString(filelist[j]);
248        filelist=(char **) RelinquishWizardMemory(filelist);
249        continue;
250      }
251    /*
252      Transfer file list to argument vector.
253    */
254    vector=(char **) ResizeQuantumMemory(vector,(size_t) *argc+count+
255      number_files+1,sizeof(*vector));
256    if (vector == (char **) NULL)
257      return(WizardFalse);
258    count--;
259    for (j=0; j < (long) number_files; j++)
260    {
261      (void) CopyWizardString(filename,path,MaxTextExtent);
262      if (*path != '\0')
263        (void) ConcatenateWizardString(filename,DirectorySeparator,
264          MaxTextExtent);
265      (void) ConcatenateWizardString(filename,filelist[j],MaxTextExtent);
266      filelist[j]=DestroyString(filelist[j]);
267      if (IsAccessible(filename) != WizardFalse)
268        {
269          char
270            path[MaxTextExtent];
271
272          *path='\0';
273          (void) ConcatenateWizardString(path,filename,MaxTextExtent);
274          vector[count++]=ConstantString(path);
275        }
276    }
277    filelist=(char **) RelinquishWizardMemory(filelist);
278  }
279  vector[count]=(char *) NULL;
280  if (IsEventLogging() != WizardFalse)
281    {
282      char
283        *command_line;
284
285      command_line=AcquireString(vector[0]);
286      for (i=1; i < count; i++)
287      {
288        (void) ConcatenateString(&command_line," {");
289        (void) ConcatenateString(&command_line,vector[i]);
290        (void) ConcatenateString(&command_line,"}");
291      }
292      (void) LogWizardEvent(ConfigureEvent,GetWizardModule(),
293        "Command line: %s",command_line);
294      command_line=DestroyString(command_line);
295    }
296  *argc=(int) count;
297  *argv=vector;
298  return(WizardTrue);
299}
300
301/*
302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303%                                                                             %
304%                                                                             %
305%                                                                             %
306+  I s D i r e c t o r y                                                      %
307%                                                                             %
308%                                                                             %
309%                                                                             %
310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311%
312%  IsDirectory() returns -1 if the directory does not exist,  1 is returned
313%  if the path represents a directory otherwise 0.
314%
315%  The format of the IsDirectory method is:
316%
317%      int IsDirectory(const char *path)
318%
319%  A description of each parameter follows.
320%
321%   o  path:  The directory path.
322%
323*/
324static int IsDirectory(const char *path)
325{
326#if !defined(X_OK)
327#define X_OK  1
328#endif
329
330  int
331    status;
332
333  struct stat
334    file_info;
335
336  if ((path == (const char *) NULL) || (*path == '\0'))
337    return(WizardFalse);
338  status=stat(path,&file_info);
339  if (status != 0)
340    return(-1);
341  if (S_ISDIR(file_info.st_mode) == 0)
342    return(0);
343  if (access(path,X_OK) != 0)
344    return(0);
345  return(1);
346}
347
348/*
349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350%                                                                             %
351%                                                                             %
352%                                                                             %
353+   L i s t F i l e s                                                         %
354%                                                                             %
355%                                                                             %
356%                                                                             %
357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358%
359%  ListFiles() reads the directory specified and returns a list of filenames
360%  contained in the directory sorted in ascending alphabetic order.
361%
362%  The format of the ListFiles function is:
363%
364%      char **ListFiles(const char *directory,const char *pattern,
365%        long *number_entries)
366%
367%  A description of each parameter follows:
368%
369%    o filelist: Method ListFiles returns a list of filenames contained
370%      in the directory.  If the directory specified cannot be read or it is
371%      a file a NULL list is returned.
372%
373%    o directory: Specifies a pointer to a text string containing a directory
374%      name.
375%
376%    o pattern: Specifies a pointer to a text string containing a pattern.
377%
378%    o number_entries:  This integer returns the number of filenames in the
379%      list.
380%
381*/
382
383#if defined(__cplusplus) || defined(c_plusplus)
384extern "C" {
385#endif
386
387static int FileCompare(const void *x,const void *y)
388{
389  register const char
390    **p,
391    **q;
392
393  p=(const char **) x;
394  q=(const char **) y;
395  return(LocaleCompare(*p,*q));
396}
397
398#if defined(__cplusplus) || defined(c_plusplus)
399}
400#endif
401
402static inline int WizardReadDirectory(DIR *directory,struct dirent *entry,
403  struct dirent **result)
404{
405#if defined(MAGICKCORE_HAVE_READDIR_R)
406  return(readdir_r(directory,entry,result));
407#else
408  (void) entry;
409  errno=0;
410  *result=readdir(directory);
411  return(errno);
412#endif
413}
414
415static char **ListFiles(const char *directory,const char *pattern,
416  unsigned long *number_entries)
417{
418  char
419    **filelist;
420
421  DIR
422    *current_directory;
423
424  struct dirent
425    *buffer,
426    *entry;
427
428  unsigned long
429    max_entries;
430
431  /*
432    Open directory.
433  */
434  assert(directory != (const char *) NULL);
435  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",directory);
436  assert(pattern != (const char *) NULL);
437  assert(number_entries != (unsigned long *) NULL);
438  *number_entries=0;
439  current_directory=opendir(directory);
440  if (current_directory == (DIR *) NULL)
441    return((char **) NULL);
442  /*
443    Allocate filelist.
444  */
445  max_entries=2048;
446  filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
447    sizeof(*filelist));
448  if (filelist == (char **) NULL)
449    {
450      (void) closedir(current_directory);
451      return((char **) NULL);
452    }
453  /*
454    Save the current and change to the new directory.
455  */
456  buffer=(struct dirent *) AcquireWizardMemory(sizeof(*buffer)+FILENAME_MAX+
457    MaxTextExtent);
458  if (buffer == (struct dirent *) NULL)
459    ThrowFatalException(ResourceFatalError,"memory allocation failed `%s'");
460  while ((WizardReadDirectory(current_directory,buffer,&entry) == 0) &&
461         (entry != (struct dirent *) NULL))
462  {
463    if (*entry->d_name == '.')
464      continue;
465    if ((IsDirectory(entry->d_name) > 0) ||
466#if defined(__WINDOWS__)
467        (GlobExpression(entry->d_name,pattern,WizardTrue) != WizardFalse))
468#else
469        (GlobExpression(entry->d_name,pattern,WizardFalse) != WizardFalse))
470#endif
471      {
472        if (*number_entries >= max_entries)
473          {
474            /*
475              Extend the file list.
476            */
477            max_entries<<=1;
478            filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
479              max_entries,sizeof(*filelist));
480            if (filelist == (char **) NULL)
481              break;
482          }
483#if defined(vms)
484        {
485          register char
486            *p;
487
488          p=strchr(entry->d_name,';');
489          if (p)
490            *p='\0';
491          if (*number_entries > 0)
492            if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
493              continue;
494        }
495#endif
496        filelist[*number_entries]=(char *) AcquireString(entry->d_name);
497        if (IsDirectory(entry->d_name) > 0)
498          (void) ConcatenateWizardString(filelist[*number_entries],
499            DirectorySeparator,MaxTextExtent);
500        (*number_entries)++;
501      }
502  }
503  buffer=(struct dirent *) RelinquishWizardMemory(buffer);
504  (void) closedir(current_directory);
505  if (filelist == (char **) NULL)
506    return((char **) NULL);
507  /*
508    Sort filelist in ascending order.
509  */
510  qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
511    FileCompare);
512  return(filelist);
513}
Note: See TracBrowser for help on using the browser.