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
/* ftw() for DJGPP.
3
 *
4
 * Recursively descent the directory hierarchy rooted in DIR,
5
 * calling FUNC for each object in the hierarchy.
6
 *
7
 * Copyright (c) 1995 Eli Zaretskii 
8
 *
9
 * This software may be used freely as long as this copyright notice is
10
 * left intact.  There is no warranty on this software.
11
 *
12
 */
13
 
14
#include 
15
#include 
16
#include 
17
#include 
18
#include 
19
#include 
20
#include 
21
#include 
22
#include 
23
 
24
static int
25
walk_dir(char *path, int (*func)(const char *, struct stat *, int))
26
{
27
  DIR *dp;
28
  struct dirent *de;
29
  struct stat stbuf;
30
  int flag;
31
  int e = errno;
32
  int pathlen = strlen(path);
33
 
34
  if ((dp = opendir(path)) == 0)
35
    return -1;
36
 
37
  for (errno = 0; (de = readdir(dp)) != 0; errno = 0)
38
    {
39
      int func_result;
40
      char lastc = de->d_name[de->d_namlen - 1];
41
 
42
      /* Skip `.' and `..' entries.  Checking the last char is enough,
43
         because readdir will never return a filename which ends with
44
         a dot.  */
45
      if (lastc == '.')
46
        continue;
47
 
48
      /* Append found name to directory path.  */
49
      if (pathlen + de->d_namlen + 1 > FILENAME_MAX)
50
        {
51
          (void)closedir(dp);
52
          errno = ENAMETOOLONG;
53
          return -1;
54
        }
55
      if (path[pathlen-1] == '/' || path[pathlen-1] == '\\')
56
        pathlen--;
57
      path[pathlen] = '/';
58
      strcpy(path + pathlen + 1, de->d_name);
59
 
60
      if (stat(path, &stbuf) < 0)
61
        flag = FTW_NS;
62
      else if (S_ISDIR(stbuf.st_mode))
63
        flag = FTW_D;
64
      else if (S_ISLABEL(stbuf.st_mode))
65
        flag = FTW_VL;
66
      else
67
        flag = FTW_F;
68
 
69
      /* Invoke FUNC() on this object.  */
70
      errno = e;
71
      if ((func_result = (*func)(path, &stbuf, flag)) != 0)
72
        {
73
          (void)closedir(dp);
74
          return func_result;
75
        }
76
 
77
      /* If this is a directory, walk its siblings.  */
78
      if (flag == FTW_D)
79
        {
80
          int subwalk_result;
81
 
82
          errno = e;
83
          if ((subwalk_result = walk_dir(path, func)) != 0)
84
            {
85
              (void)closedir(dp);
86
              return subwalk_result;
87
            }
88
        }
89
 
90
      /* Erase D_NAME[] from PATH.  */
91
      path[pathlen] = '\0';
92
    }
93
 
94
  (void)closedir(dp);
95
  if (errno == 0)   /* normal case: this subtree exhausted */
96
    {
97
      errno = e;/* restore errno from previous syscall */
98
      return 0;
99
    }
100
  else
101
    return -1;      /* with whatever errno was set by readdir() */
102
}
103
 
104
int
105
ftw(const char *dir, int (*func)(const char *, struct stat *, int),
106
    int ignored)
107
{
108
  int flag;
109
  unsigned char pathbuf[FILENAME_MAX];
110
  int dirattr;
111
  int len;
112
  int e = errno;
113
 
114
  ignored = ignored;        /* pacify -Wall */
115
 
116
  if (dir == 0 || func == 0)
117
    {
118
      errno = EFAULT;
119
      return -1;
120
    }
121
 
122
  if (*dir == '\0')
123
    {
124
      errno = ENOENT;
125
      return -1;
126
    }
127
 
128
  strcpy(pathbuf, dir);
129
  len = strlen(pathbuf);
130
  if (pathbuf[len-1] == ':')
131
    {
132
      pathbuf[len++] = '.';
133
      pathbuf[len] = '\0';
134
    }
135
 
136
  /* Fail for non-directories.  */
137
  errno = 0;
138
  dirattr = _chmod(pathbuf, 0, 0);
139
  if (errno == ENOENT)
140
    return -1;
141
  else if ((dirattr & 0x10) != 0x10)
142
    {
143
      errno = ENOTDIR;
144
      return -1;
145
    }
146
  else
147
    {
148
      int func_result;
149
      struct stat stbuf;
150
 
151
      if (stat(pathbuf, &stbuf) < 0)
152
        flag = FTW_NS;
153
      else
154
        flag = FTW_D;
155
      errno = e;
156
      if ((func_result = (*func)(pathbuf, &stbuf, flag)) != 0)
157
        return func_result;
158
 
159
      return walk_dir(pathbuf, func);
160
    }
161
}
162
 
163
#ifdef  TEST
164
 
165
#include 
166
 
167
int
168
ftw_walker(const char *path, struct stat *sb, int flag)
169
{
170
  char *base;
171
 
172
  printf("%s:\t%u\t", path, sb->st_size);
173
  if (S_ISLABEL(sb->st_mode))
174
    printf("V");
175
  if (S_ISDIR(sb->st_mode))
176
    printf("D");
177
  if (S_ISCHR(sb->st_mode))
178
    printf("C");
179
  if (sb->st_mode & S_IRUSR)
180
    printf("r");
181
  if (sb->st_mode & S_IWUSR)
182
    printf("w");
183
  if (sb->st_mode & S_IXUSR)
184
    printf("x");
185
 
186
  if (flag == FTW_NS)
187
    printf("  !!no_stat!!");
188
  printf("\n");
189
 
190
  base = strrchr(path, '/');
191
  if (base == 0)
192
    base = strrchr(path, '\\');
193
  if (base == 0)
194
    base = strrchr(path, ':');
195
  if (strcmp(base == 0 ? path : base + 1, "xxxxx") == 0)
196
    return 8;
197
  return 0;
198
}
199
 
200
int
201
main(int argc, char *argv[])
202
{
203
  if (argc > 1)
204
    {
205
      char msg[80];
206
 
207
      sprintf(msg, "file_tree_walk: %d",
208
                   ftw(argv[1], ftw_walker, 0));
209
      if (errno)
210
        perror(msg);
211
      else
212
        puts(msg);
213
    }
214
  else
215
    printf("Usage: %s dir\n", argv[0]);
216
 
217
  return 0;
218
}
219
 
220
#endif