Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4973 right-hear 1
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
2
/*
3
 * Recursively descent the directory hierarchy rooted in DIR,
4
 * calling FUNC for each object in the hierarchy.  We cannot
5
 * use ftw(), because it uses some non-ANSI functions which
6
 * will pollute ANSI namespace, while we need this function
7
 * in some ANSI functions (e.g., rename()).  Thus, this function
8
 * is closely modeled on ftw(), but uses DOS directory search
9
 * functions and structures instead of opendir()/readdir()/stat().
10
 *
11
 * Copyright (c) 1995 Eli Zaretskii 
12
 *
13
 * This software may be used freely as long as this copyright notice is
14
 * left intact.  There is no warranty on this software.
15
 *
16
 */
17
 
18
#include 
19
#include 
20
#include 
21
#include 
22
#include 
23
#include 
24
 
25
#define FA_ALL  (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_LABEL|FA_DIREC|FA_ARCH)
26
 
27
int
28
__file_tree_walk(const char *dir,
29
               int (*func)(const char *, const struct ffblk *))
30
{
31
  struct ffblk  ff;
32
  unsigned char searchspec[FILENAME_MAX];
33
  unsigned char found[FILENAME_MAX], *dir_end;
34
  int e = errno;
35
 
36
  if (dir == 0 || func == 0)
37
    {
38
      errno = EFAULT;
39
      return -1;
40
    }
41
 
42
  if (*dir == '\0')
43
    {
44
      errno = ENOENT;
45
      return -1;
46
    }
47
 
48
  /* Construct the search spec for findfirst().  Treat ``d:'' as ``d:.''.  */
49
  strcpy(searchspec, dir);
50
  dir_end = searchspec + strlen(searchspec) - 1;
51
  if (*dir_end == ':')
52
    {
53
      *++dir_end = '.';
54
      *++dir_end = '\0';
55
    }
56
  else if (*dir_end == '/' || *dir_end == '\\')
57
    *dir_end   = '\0';
58
  else
59
    ++dir_end;
60
  strcpy(dir_end, "/*.*");
61
 
62
  /* Prepare the buffer where the full pathname of the found files
63
     will be placed.  */
64
  strcpy(found, dir);
65
  dir_end = found + strlen(found) - 1;
66
  if (*dir_end == ':')
67
    {
68
      *++dir_end = '.';
69
      dir_end[1] = '\0';
70
    }
71
  if (*dir_end != '/' && *dir_end != '\\')
72
    {
73
      /* Try to preserve user's forward/backward slash style.  */
74
      *++dir_end = strchr(found, '\\') == 0 ? '/': '\\';
75
      *++dir_end   = '\0';
76
    }
77
  else
78
    ++dir_end;
79
 
80
  if (findfirst(searchspec, &ff, FA_ALL))
81
    return -1;
82
 
83
  do
84
    {
85
      int func_result;
86
      unsigned char *p = dir_end;
87
 
88
      /* Skip `.' and `..' entries.  */
89
      if (ff.ff_name[0] == '.' &&
90
          (ff.ff_name[1] == '\0' || ff.ff_name[1] == '.'))
91
        continue;
92
 
93
      /* Construct full pathname in FOUND[].  */
94
      strcpy(dir_end, ff.ff_name);
95
 
96
      /* Convert name of found file to lower-case.  Cannot use
97
         strlwr() because it's non-ANSI.  Sigh... */
98
      while (*p)
99
        *p++ = tolower(*p);
100
 
101
      /* Invoke FUNC() on this file.  */
102
      if ((func_result = (*func)(found, &ff)) != 0)
103
        return func_result;
104
 
105
      /* If this is a directory, walk its siblings.  */
106
      if (ff.ff_attrib & 0x10)
107
        {
108
          int subwalk_result;
109
 
110
          if ((subwalk_result = __file_tree_walk(found, func)) != 0)
111
            return subwalk_result;
112
        }
113
    } while (findnext(&ff) == 0);
114
 
115
  if (errno == ENMFILE)     /* normal case: tree exhausted */
116
    {
117
      errno = e;    /* restore errno from previous syscall */
118
      return 0;
119
    }
120
 
121
  return -1;                /* error; errno set by findnext() */
122
}
123
 
124
#ifdef  TEST
125
 
126
#include 
127
 
128
int
129
ff_walker(const char *path, const struct ffblk *ff)
130
{
131
  printf("%s:\t%lu\t", path, ff->ff_fsize);
132
  if (ff->ff_attrib & 1)
133
    printf("R");
134
  if (ff->ff_attrib & 2)
135
    printf("H");
136
  if (ff->ff_attrib & 4)
137
    printf("S");
138
  if (ff->ff_attrib & 8)
139
    printf("V");
140
  if (ff->ff_attrib & 0x10)
141
    printf("D");
142
  if (ff->ff_attrib & 0x20)
143
    printf("A");
144
  printf("\n");
145
 
146
  if (strcmp(ff->ff_name, "XXXXX") == 0)
147
    return 8;
148
  return 0;
149
}
150
 
151
int
152
main(int argc, char *argv[])
153
{
154
  if (argc > 1)
155
    {
156
      char msg[80];
157
 
158
      sprintf(msg, "file_tree_walk: %d",
159
                   file_tree_walk(argv[1], ff_walker));
160
      if (errno)
161
        perror(msg);
162
      else
163
        puts(msg);
164
    }
165
  else
166
    printf("Usage: %s dir\n", argv[0]);
167
 
168
  return 0;
169
}
170
 
171
#endif