• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 #include "android/utils/dirscanner.h"
13 #include "android/utils/bufprint.h"
14 #include "android/utils/system.h"
15 #include "android/utils/path.h"
16 #include <stddef.h>
17 
18 #define  DIRSCANNER_BASE     \
19     char  root[PATH_MAX];    \
20     int   rootLen;           \
21     char  full[PATH_MAX];    \
22 
23 
24 #if _WIN32
25 
26 #include <io.h>
27 
28 struct DirScanner {
29     DIRSCANNER_BASE
30     intptr_t            findIndex1;
31     struct _finddata_t  findData;
32 };
33 
34 /* note: findIndex1 contains the find index + 1
35  *       so a value of 0 means 'invalid'
36  */
37 
38 static int
_dirScannerInit(DirScanner * s)39 _dirScannerInit( DirScanner*  s )
40 {
41     char*  p   = s->root + s->rootLen;
42     char*  end = s->root + sizeof s->root;
43     int    ret;
44 
45     /* create file spec by appending \* to root */
46     p = bufprint(p, end, "\\*");
47     if (p >= end)
48         return -1;
49 
50     ret = _findfirst(s->root, &s->findData);
51 
52     s->findIndex1 = ret+1;
53     return ret;
54 }
55 
56 static void
_dirScanner_done(DirScanner * s)57 _dirScanner_done( DirScanner*  s )
58 {
59     if (s->findIndex1 > 0) {
60         _findclose(s->findIndex1-1);
61         s->findIndex1 = 0;
62     }
63 }
64 
65 const char*
dirScanner_next(DirScanner * s)66 dirScanner_next( DirScanner*  s )
67 {
68     char*  ret = NULL;
69 
70     if (!s || s->findIndex1 <= 0)
71         return NULL;
72 
73     while (ret == NULL) {
74         ret = s->findData.name;
75 
76         /* ignore special directories */
77         if (!strcmp(ret, ".") || !strcmp(ret, "..")) {
78             ret = NULL;
79         }
80         /* find next one */
81         if (_findnext(s->findIndex1-1, &s->findData) < 0) {
82             _dirScanner_done(s);
83             break;
84         }
85     }
86     return ret;
87 }
88 
89 #else /* !_WIN32 */
90 
91 #include <dirent.h>
92 struct DirScanner {
93     DIRSCANNER_BASE
94     DIR*            dir;
95     struct dirent*  entry;
96 };
97 
98 static int
_dirScannerInit(DirScanner * s)99 _dirScannerInit( DirScanner*  s )
100 {
101     s->dir = opendir(s->root);
102 
103     if (s->dir == NULL)
104         return -1;
105 
106     s->entry = NULL;
107     return 0;
108 }
109 
110 static void
_dirScanner_done(DirScanner * s)111 _dirScanner_done( DirScanner*  s )
112 {
113     if (s->dir) {
114         closedir(s->dir);
115         s->dir = NULL;
116     }
117 }
118 
119 const char*
dirScanner_next(DirScanner * s)120 dirScanner_next( DirScanner*  s )
121 {
122     char*  ret = NULL;
123 
124     if (!s || s->dir == NULL)
125         return NULL;
126 
127     for (;;)
128     {
129         /* read new entry if needed */
130         s->entry = readdir(s->dir);
131         if (s->entry == NULL) {
132             _dirScanner_done(s);
133             break;
134         }
135 
136         /* ignore special directories */
137         ret = s->entry->d_name;
138 
139         if (!strcmp(ret,".") || !strcmp(ret,"..")) {
140             ret = NULL;
141             continue;
142         }
143         break;
144     }
145     return ret;
146 }
147 
148 #endif /* !_WIN32 */
149 
150 DirScanner*
dirScanner_new(const char * rootPath)151 dirScanner_new ( const char*  rootPath )
152 {
153     DirScanner*  s   = android_alloc0(sizeof *s);
154     char*        p   = s->root;
155     char*        end = p + sizeof s->root;
156 
157     p = bufprint(p, end, "%s", rootPath);
158     if (p >= end)
159         goto FAIL;
160 
161     s->rootLen = (p - s->root);
162 
163     if (_dirScannerInit(s) < 0)
164         goto FAIL;
165 
166     return s;
167 
168 FAIL:
169     dirScanner_free(s);
170     return NULL;
171 }
172 
173 
174 void
dirScanner_free(DirScanner * s)175 dirScanner_free( DirScanner*  s )
176 {
177     if (!s)
178         return;
179 
180     _dirScanner_done(s);
181     AFREE(s);
182 }
183 
184 
185 const char*
dirScanner_nextFull(DirScanner * s)186 dirScanner_nextFull( DirScanner*  s )
187 {
188     const char*  name = dirScanner_next(s);
189     char*        p;
190     char*        end;
191 
192     if (name == NULL)
193         return NULL;
194 
195     p   = s->full;
196     end = p + sizeof s->full;
197 
198     p = bufprint(p, end, "%.*s/%s", s->rootLen, s->root, name);
199     if (p >= end) {
200         /* ignore if the full name is too long */
201         return dirScanner_nextFull(s);
202     }
203     return s->full;
204 }
205