18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms. 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful, 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details. 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/ 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/dirscanner.h" 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/bufprint.h" 1418fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner#include "android/utils/system.h" 1518fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner#include "android/utils/path.h" 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stddef.h> 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DIRSCANNER_BASE \ 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char root[PATH_MAX]; \ 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rootLen; \ 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char full[PATH_MAX]; \ 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if _WIN32 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <io.h> 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct DirScanner { 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DIRSCANNER_BASE 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project intptr_t findIndex1; 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct _finddata_t findData; 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* note: findIndex1 contains the find index + 1 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so a value of 0 means 'invalid' 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project_dirScannerInit( DirScanner* s ) 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* p = s->root + s->rootLen; 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* end = s->root + sizeof s->root; 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* create file spec by appending \* to root */ 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p = bufprint(p, end, "\\*"); 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (p >= end) 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = _findfirst(s->root, &s->findData); 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->findIndex1 = ret+1; 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project_dirScanner_done( DirScanner* s ) 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->findIndex1 > 0) { 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project _findclose(s->findIndex1-1); 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->findIndex1 = 0; 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char* 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectdirScanner_next( DirScanner* s ) 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* ret = NULL; 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s || s->findIndex1 <= 0) 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (ret == NULL) { 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = s->findData.name; 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ignore special directories */ 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!strcmp(ret, ".") || !strcmp(ret, "..")) { 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = NULL; 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* find next one */ 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (_findnext(s->findIndex1-1, &s->findData) < 0) { 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project _dirScanner_done(s); 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !_WIN32 */ 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <dirent.h> 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct DirScanner { 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DIRSCANNER_BASE 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DIR* dir; 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct dirent* entry; 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project_dirScannerInit( DirScanner* s ) 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->dir = opendir(s->root); 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->dir == NULL) 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->entry = NULL; 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project_dirScanner_done( DirScanner* s ) 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->dir) { 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project closedir(s->dir); 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->dir = NULL; 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char* 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectdirScanner_next( DirScanner* s ) 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* ret = NULL; 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s || s->dir == NULL) 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (;;) 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* read new entry if needed */ 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->entry = readdir(s->dir); 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->entry == NULL) { 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project _dirScanner_done(s); 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ignore special directories */ 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = s->entry->d_name; 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!strcmp(ret,".") || !strcmp(ret,"..")) { 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = NULL; 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !_WIN32 */ 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectDirScanner* 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectdirScanner_new ( const char* rootPath ) 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 15318fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner DirScanner* s = android_alloc0(sizeof *s); 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* p = s->root; 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* end = p + sizeof s->root; 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p = bufprint(p, end, "%s", rootPath); 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (p >= end) 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto FAIL; 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->rootLen = (p - s->root); 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (_dirScannerInit(s) < 0) 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto FAIL; 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return s; 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFAIL: 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dirScanner_free(s); 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectdirScanner_free( DirScanner* s ) 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s) 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project _dirScanner_done(s); 18118fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner AFREE(s); 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char* 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectdirScanner_nextFull( DirScanner* s ) 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const char* name = dirScanner_next(s); 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* p; 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char* end; 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (name == NULL) 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p = s->full; 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project end = p + sizeof s->full; 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p = bufprint(p, end, "%.*s/%s", s->rootLen, s->root, name); 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (p >= end) { 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ignore if the full name is too long */ 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return dirScanner_nextFull(s); 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return s->full; 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 205