Annotation of hatari/src/scandir.c, revision 1.1.1.10

1.1       root        1: /*
                      2:   Hatari - scandir.c
                      3: 
1.1.1.8   root        4:   This file is distributed under the GNU General Public License, version 2
                      5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
                      7:   scandir function for BEOS, SunOS etc..
                      8: */
1.1.1.5   root        9: const char ScanDir_fileid[] = "Hatari scandir.c : " __DATE__ " " __TIME__;
1.1       root       10: 
                     11: #include <string.h>
                     12: #include <stdio.h>
1.1.1.2   root       13: #include <stdlib.h>
1.1       root       14: #include <sys/types.h>
                     15: #include <sys/stat.h>
                     16: #include <fcntl.h>
                     17: #include <unistd.h>
                     18: 
                     19: #include "scandir.h"
1.1.1.2   root       20: #include "log.h"
1.1       root       21: 
                     22: /*-----------------------------------------------------------------------
1.1.1.7   root       23:  * Here come alphasort and scandir for POSIX-like OSes
1.1       root       24:  *-----------------------------------------------------------------------*/
1.1.1.7   root       25: #if !defined(WIN32) && !defined(__CEGCC__)
1.1       root       26: 
                     27: 
1.1.1.7   root       28: /**
                     29:  * Alphabetic order comparison routine.
                     30:  */
                     31: #if !HAVE_ALPHASORT
1.1.1.9   root       32: int alphasort(const struct dirent **d1, const struct dirent **d2)
1.1.1.7   root       33: {
1.1.1.9   root       34:        return strcmp((*d1)->d_name, (*d2)->d_name);
1.1.1.7   root       35: }
                     36: #endif
                     37: 
                     38: 
                     39: #if !HAVE_SCANDIR
                     40: 
                     41: #undef DIRSIZ
1.1       root       42: #define DIRSIZ(dp)                                          \
                     43:                ((sizeof(struct dirent) - sizeof(dp)->d_name) +     \
                     44:                (((dp)->d_reclen + 1 + 3) &~ 3))
                     45: 
1.1.1.2   root       46: #if (defined(__sun) && defined(__SVR4)) || defined(__CEGCC__)
1.1       root       47: # define dirfd(d) ((d)->dd_fd)
                     48: #elif defined(__BEOS__)
                     49: # define dirfd(d) ((d)->fd)
                     50: #endif
                     51: 
                     52: 
1.1.1.2   root       53: /**
                     54:  * Scan a directory for all its entries
1.1.1.6   root       55:  * Return -1 on error, number of entries on success
1.1.1.2   root       56:  */
1.1.1.9   root       57: int scandir(const char *dirname, struct dirent ***namelist,
                     58:             int (*sdfilter)(const struct dirent *),
                     59:             int (*dcomp)(const struct dirent **, const struct dirent **))
1.1       root       60: {
1.1.1.6   root       61:        struct dirent *d, *p = NULL, **names = NULL;
1.1       root       62:        struct stat stb;
1.1.1.6   root       63:        size_t nitems = 0;
1.1       root       64:        size_t arraysz;
                     65:        DIR *dirp;
                     66: 
                     67:        if ((dirp = opendir(dirname)) == NULL)
1.1.1.6   root       68:                goto error_out;
1.1       root       69: 
                     70:        if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.6   root       71:                goto error_out;
1.1       root       72: 
                     73:        /*
                     74:         * estimate the array size by taking the size of the directory file
                     75:         * and dividing it by a multiple of the minimum size entry.
                     76:         */
                     77:        arraysz = (stb.st_size / 24);
                     78: 
                     79:        names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
                     80:        if (names == NULL)
1.1.1.6   root       81:                goto error_out;
1.1       root       82: 
                     83:        while ((d = readdir(dirp)) != NULL)
                     84:        {
                     85: 
                     86:                if (sdfilter != NULL && !(*sdfilter)(d))
                     87:                        continue;       /* just selected names */
                     88: 
                     89:                /*
                     90:                 * Make a minimum size copy of the data
                     91:                 */
                     92: 
                     93:                p = (struct dirent *)malloc(DIRSIZ(d));
                     94:                if (p == NULL)
1.1.1.6   root       95:                        goto error_out;
1.1       root       96: 
                     97:                p->d_ino = d->d_ino;
                     98:                p->d_reclen = d->d_reclen;
                     99:                /*p->d_namlen = d->d_namlen;*/
                    100:                memcpy(p->d_name, d->d_name, p->d_reclen + 1);
                    101: 
                    102:                /*
                    103:                 * Check to make sure the array has space left and
                    104:                 * realloc the maximum size.
                    105:                 */
                    106: 
1.1.1.6   root      107:                if ((nitems+1) >= arraysz)
1.1       root      108:                {
1.1.1.6   root      109:                        struct dirent **tmp;
                    110:                        
1.1       root      111:                        if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.6   root      112:                                goto error_out;   /* just might have grown */
1.1       root      113: 
                    114:                        arraysz = stb.st_size / 12;
                    115: 
1.1.1.6   root      116:                        tmp = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
                    117:                        if (tmp == NULL)
                    118:                                goto error_out;
                    119:                        names = tmp;
1.1       root      120:                }
                    121: 
1.1.1.6   root      122:                names[nitems++] = p;
                    123:                p = NULL;
1.1       root      124:        }
                    125: 
                    126:        closedir(dirp);
                    127: 
                    128:        if (nitems && dcomp != NULL)
1.1.1.9   root      129:                qsort(names, nitems, sizeof(struct dirent *),
                    130:                      (int (*)(const void *, const void *))dcomp);
1.1       root      131: 
                    132:        *namelist = names;
                    133: 
                    134:        return nitems;
1.1.1.6   root      135: 
                    136: error_out:
                    137:        if (names)
                    138:        {
                    139:                int i;
                    140:                for (i = 0; i < nitems; i++)
                    141:                        free(names[i]);
                    142:                free(names);
                    143:        }
                    144:        if (dirp)
                    145:                closedir(dirp);
                    146:        return -1;
1.1       root      147: }
1.1.1.7   root      148: #endif /* !HAVE_SCANDIR */
1.1       root      149: 
                    150: 
1.1.1.7   root      151: #endif /* !WIN32 */
1.1       root      152: 
                    153: 
                    154: /*-----------------------------------------------------------------------
                    155:  * Here come alphasort and scandir for Windows
                    156:  *-----------------------------------------------------------------------*/
1.1.1.2   root      157: #if defined(WIN32) || defined(__CEGCC__)
1.1       root      158: 
                    159: #include <windows.h>
1.1.1.2   root      160: #include <wchar.h>
1.1       root      161: 
                    162: /*-----------------------------------------------------------------------*/
1.1.1.2   root      163: /**
                    164:  * Alphabetic order comparison routine.
                    165:  */
1.1.1.9   root      166: int alphasort(const struct dirent **d1, const struct dirent **d2)
1.1       root      167: {
1.1.1.9   root      168:        return stricmp((*d1)->d_name, (*d2)->d_name);
1.1       root      169: }
                    170: 
                    171: /*-----------------------------------------------------------------------*/
1.1.1.2   root      172: /**
                    173:  * Scan a directory for all its entries
                    174:  */
1.1.1.9   root      175: int scandir(const char *dirname, struct dirent ***namelist,
                    176:             int (*sdfilter)(const struct dirent *),
                    177:             int (*dcomp)(const struct dirent **, const struct dirent **))
1.1       root      178: {
                    179:        int len;
                    180:        char *findIn, *d;
                    181:        WIN32_FIND_DATA find;
                    182:        HANDLE h;
                    183:        int nDir = 0, NDir = 0;
                    184:        struct dirent **dir = 0, *selectDir;
                    185:        unsigned long ret;
                    186: 
                    187:        len    = strlen(dirname);
                    188:        findIn = (char *)malloc(len+5);
1.1.1.2   root      189:        if (!findIn)
                    190:                return -1;
                    191: 
1.1       root      192:        strcpy(findIn, dirname);
1.1.1.2   root      193:        Log_Printf(LOG_DEBUG, "scandir : findIn orign='%s'\n", findIn);
                    194: 
1.1       root      195:        for (d = findIn; *d; d++)
                    196:                if (*d=='/')
                    197:                        *d='\\';
                    198:        if ((len==0))
                    199:        {
                    200:                strcpy(findIn, ".\\*");
                    201:        }
                    202:        if ((len==1)&& (d[-1]=='.'))
                    203:        {
                    204:                strcpy(findIn, ".\\*");
                    205:        }
                    206:        if ((len>0) && (d[-1]=='\\'))
                    207:        {
                    208:                *d++ = '*';
                    209:                *d = 0;
                    210:        }
                    211:        if ((len>1) && (d[-1]=='.') && (d[-2]=='\\'))
                    212:        {
                    213:                d[-1] = '*';
                    214:        }
1.1.1.5   root      215:        if ((len>1) && !(d[-2]=='\\' && d[-1]=='*') )
1.1       root      216:        {
                    217:                *d++ = '\\';
                    218:                *d++ = '*';
                    219:                *d = 0;
                    220:        }
                    221: 
1.1.1.2   root      222:        Log_Printf(LOG_DEBUG, "scandir : findIn processed='%s'\n", findIn);
                    223: 
                    224: #if defined(__CEGCC__)
                    225:        void *findInW = NULL;
                    226:        findInW = malloc((len+6)*2);
                    227:        if (!findInW)
                    228:                return -1;
                    229:        mbstowcs(findInW, findIn, len+6);
                    230:        h = FindFirstFileW(findInW, &find);
                    231: #else
                    232:        h = FindFirstFile(findIn, &find);
                    233: #endif
                    234: 
                    235:        if (h == INVALID_HANDLE_VALUE)
1.1       root      236:        {
1.1.1.2   root      237:                Log_Printf(LOG_DEBUG, "scandir : FindFirstFile error\n");
1.1       root      238:                ret = GetLastError();
                    239:                if (ret != ERROR_NO_MORE_FILES)
                    240:                {
                    241:                        // TODO: return some error code
                    242:                }
                    243:                *namelist = dir;
                    244:                return nDir;
                    245:        }
1.1.1.2   root      246: 
1.1       root      247:        do
                    248:        {
1.1.1.2   root      249:                selectDir=(struct dirent*)malloc(sizeof(struct dirent)+lstrlen(find.cFileName)+1);
                    250: #if defined(__CEGCC__)
                    251:                wcstombs(selectDir->d_name, find.cFileName, lstrlen(find.cFileName)+1);
                    252: #else
1.1       root      253:                strcpy(selectDir->d_name, find.cFileName);
1.1.1.2   root      254: #endif
                    255:                //Log_Printf(LOG_DEBUG, "scandir : findFile='%s'\n", selectDir->d_name);
1.1       root      256:                if (!sdfilter || (*sdfilter)(selectDir))
                    257:                {
                    258:                        if (nDir==NDir)
                    259:                        {
                    260:                                struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), NDir+33);
                    261:                                if (NDir)
                    262:                                        memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
1.1.1.10! root      263:                                free(dir);
1.1       root      264:                                dir = tempDir;
                    265:                                NDir += 32;
                    266:                        }
                    267:                        dir[nDir] = selectDir;
                    268:                        nDir++;
                    269:                        dir[nDir] = 0;
                    270:                }
                    271:                else
                    272:                {
                    273:                        free(selectDir);
                    274:                }
1.1.1.5   root      275: 
1.1.1.2   root      276: #if defined(__CEGCC__)
                    277:                ret = FindNextFileW(h, &find);
                    278: #else
                    279:                ret = FindNextFile(h, &find);
                    280: #endif
1.1       root      281:        }
1.1.1.2   root      282:        while (ret);
                    283: 
1.1       root      284:        ret = GetLastError();
                    285:        if (ret != ERROR_NO_MORE_FILES)
                    286:        {
                    287:                // TODO: return some error code
1.1.1.3   root      288:                Log_Printf(LOG_DEBUG, "scandir: last error = %ld\n", ret);
1.1       root      289:        }
1.1.1.2   root      290: 
1.1       root      291:        FindClose(h);
                    292: 
1.1.1.2   root      293:        free(findIn);
                    294: 
                    295: #if defined(__CEGCC__)
                    296:        free(findInW);
                    297: #endif
1.1       root      298: 
                    299:        if (dcomp)
1.1.1.9   root      300:                qsort(dir, nDir, sizeof(*dir),
                    301:                      (int (*)(const void *, const void *))dcomp);
1.1       root      302: 
                    303:        *namelist = dir;
                    304:        return nDir;
                    305: }
                    306: 
                    307: #endif /* WIN32 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.