Home | History | Annotate | Download | only in utils
      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
     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
     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*
     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
     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
    110 _dirScanner_done( DirScanner*  s )
    111 {
    112     if (s->dir) {
    113         closedir(s->dir);
    114         s->dir = NULL;
    115     }
    116 }
    117 
    118 const char*
    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*
    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
    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*
    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