• 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 "qemu-common.h"
15 #include <stddef.h>
16 
17 #define  DIRSCANNER_BASE     \
18     char  root[PATH_MAX];    \
19     int   rootLen;           \
20     char  full[PATH_MAX];    \
21 
22 
23 #if _WIN32
24 
25 #include <io.h>
26 
27 struct DirScanner {
28     DIRSCANNER_BASE
29     intptr_t            findIndex1;
30     struct _finddata_t  findData;
31 };
32 
33 /* note: findIndex1 contains the find index + 1
34  *       so a value of 0 means 'invalid'
35  */
36 
37 static int
_dirScannerInit(DirScanner * s)38 _dirScannerInit( DirScanner*  s )
39 {
40     char*  p   = s->root + s->rootLen;
41     char*  end = s->root + sizeof s->root;
42     int    ret;
43 
44     /* create file spec by appending \* to root */
45     p = bufprint(p, end, "\\*");
46     if (p >= end)
47         return -1;
48 
49     ret = _findfirst(s->root, &s->findData);
50 
51     s->findIndex1 = ret+1;
52     return ret;
53 }
54 
55 static void
_dirScanner_done(DirScanner * s)56 _dirScanner_done( DirScanner*  s )
57 {
58     if (s->findIndex1 > 0) {
59         _findclose(s->findIndex1-1);
60         s->findIndex1 = 0;
61     }
62 }
63 
64 const char*
dirScanner_next(DirScanner * s)65 dirScanner_next( DirScanner*  s )
66 {
67     char*  ret = NULL;
68 
69     if (!s || s->findIndex1 <= 0)
70         return NULL;
71 
72     while (ret == NULL) {
73         ret = s->findData.name;
74 
75         /* ignore special directories */
76         if (!strcmp(ret, ".") || !strcmp(ret, "..")) {
77             ret = NULL;
78         }
79         /* find next one */
80         if (_findnext(s->findIndex1-1, &s->findData) < 0) {
81             _dirScanner_done(s);
82             break;
83         }
84     }
85     return ret;
86 }
87 
88 #else /* !_WIN32 */
89 
90 #include <dirent.h>
91 struct DirScanner {
92     DIRSCANNER_BASE
93     DIR*            dir;
94     struct dirent*  entry;
95 };
96 
97 static int
_dirScannerInit(DirScanner * s)98 _dirScannerInit( DirScanner*  s )
99 {
100     s->dir = opendir(s->root);
101 
102     if (s->dir == NULL)
103         return -1;
104 
105     s->entry = NULL;
106     return 0;
107 }
108 
109 static void
_dirScanner_done(DirScanner * s)110 _dirScanner_done( DirScanner*  s )
111 {
112     if (s->dir) {
113         closedir(s->dir);
114         s->dir = NULL;
115     }
116 }
117 
118 const char*
dirScanner_next(DirScanner * s)119 dirScanner_next( DirScanner*  s )
120 {
121     char*  ret = NULL;
122 
123     if (!s || s->dir == NULL)
124         return NULL;
125 
126     for (;;)
127     {
128         /* read new entry if needed */
129         s->entry = readdir(s->dir);
130         if (s->entry == NULL) {
131             _dirScanner_done(s);
132             break;
133         }
134 
135         /* ignore special directories */
136         ret = s->entry->d_name;
137 
138         if (!strcmp(ret,".") || !strcmp(ret,"..")) {
139             ret = NULL;
140             continue;
141         }
142         break;
143     }
144     return ret;
145 }
146 
147 #endif /* !_WIN32 */
148 
149 DirScanner*
dirScanner_new(const char * rootPath)150 dirScanner_new ( const char*  rootPath )
151 {
152     DirScanner*  s   = qemu_mallocz(sizeof *s);
153     char*        p   = s->root;
154     char*        end = p + sizeof s->root;
155 
156     p = bufprint(p, end, "%s", rootPath);
157     if (p >= end)
158         goto FAIL;
159 
160     s->rootLen = (p - s->root);
161 
162     if (_dirScannerInit(s) < 0)
163         goto FAIL;
164 
165     return s;
166 
167 FAIL:
168     dirScanner_free(s);
169     return NULL;
170 }
171 
172 
173 void
dirScanner_free(DirScanner * s)174 dirScanner_free( DirScanner*  s )
175 {
176     if (!s)
177         return;
178 
179     _dirScanner_done(s);
180     qemu_free(s);
181 }
182 
183 
184 const char*
dirScanner_nextFull(DirScanner * s)185 dirScanner_nextFull( DirScanner*  s )
186 {
187     const char*  name = dirScanner_next(s);
188     char*        p;
189     char*        end;
190 
191     if (name == NULL)
192         return NULL;
193 
194     p   = s->full;
195     end = p + sizeof s->full;
196 
197     p = bufprint(p, end, "%.*s/%s", s->rootLen, s->root, name);
198     if (p >= end) {
199         /* ignore if the full name is too long */
200         return dirScanner_nextFull(s);
201     }
202     return s->full;
203 }
204