Annotation of previous_trunk/src/scandir.c, revision 1.1

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

unix.superglobalmegacorp.com

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