|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #if defined(LIBC_SCCS) && !defined(lint) ! 21: static char sccsid[] = "@(#)scandir.c 5.9 (Berkeley) 6/24/90"; ! 22: #endif /* LIBC_SCCS and not lint */ ! 23: ! 24: /* ! 25: * Scan the directory dirname calling select to make a list of selected ! 26: * directory entries then sort using qsort and compare routine dcomp. ! 27: * Returns the number of entries and a pointer to a list of pointers to ! 28: * struct dirent (through namelist). Returns -1 if there were any errors. ! 29: */ ! 30: ! 31: #include <sys/types.h> ! 32: #include <sys/stat.h> ! 33: #include <dirent.h> ! 34: ! 35: /* ! 36: * The DIRSIZ macro gives the minimum record length which will hold ! 37: * the directory entry. This requires the amount of space in struct dirent ! 38: * without the d_name field, plus enough space for the name with a terminating ! 39: * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. ! 40: */ ! 41: #undef DIRSIZ ! 42: #define DIRSIZ(dp) \ ! 43: ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) ! 44: ! 45: scandir(dirname, namelist, select, dcomp) ! 46: char *dirname; ! 47: struct dirent ***namelist; ! 48: int (*select)(), (*dcomp)(); ! 49: { ! 50: register struct dirent *d, *p, **names; ! 51: register int nitems; ! 52: struct stat stb; ! 53: long arraysz; ! 54: DIR *dirp; ! 55: ! 56: if ((dirp = opendir(dirname)) == NULL) ! 57: return(-1); ! 58: if (fstat(dirp->dd_fd, &stb) < 0) ! 59: return(-1); ! 60: ! 61: /* ! 62: * estimate the array size by taking the size of the directory file ! 63: * and dividing it by a multiple of the minimum size entry. ! 64: */ ! 65: arraysz = (stb.st_size / 24); ! 66: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); ! 67: if (names == NULL) ! 68: return(-1); ! 69: ! 70: nitems = 0; ! 71: while ((d = readdir(dirp)) != NULL) { ! 72: if (select != NULL && !(*select)(d)) ! 73: continue; /* just selected names */ ! 74: /* ! 75: * Make a minimum size copy of the data ! 76: */ ! 77: p = (struct dirent *)malloc(DIRSIZ(d)); ! 78: if (p == NULL) ! 79: return(-1); ! 80: p->d_ino = d->d_ino; ! 81: p->d_reclen = d->d_reclen; ! 82: p->d_namlen = d->d_namlen; ! 83: bcopy(d->d_name, p->d_name, p->d_namlen + 1); ! 84: /* ! 85: * Check to make sure the array has space left and ! 86: * realloc the maximum size. ! 87: */ ! 88: if (++nitems >= arraysz) { ! 89: if (fstat(dirp->dd_fd, &stb) < 0) ! 90: return(-1); /* just might have grown */ ! 91: arraysz = stb.st_size / 12; ! 92: names = (struct dirent **)realloc((char *)names, ! 93: arraysz * sizeof(struct dirent *)); ! 94: if (names == NULL) ! 95: return(-1); ! 96: } ! 97: names[nitems-1] = p; ! 98: } ! 99: closedir(dirp); ! 100: if (nitems && dcomp != NULL) ! 101: qsort(names, nitems, sizeof(struct dirent *), dcomp); ! 102: *namelist = names; ! 103: return(nitems); ! 104: } ! 105: ! 106: /* ! 107: * Alphabetic order comparison routine for those who want it. ! 108: */ ! 109: alphasort(d1, d2) ! 110: void *d1, *d2; ! 111: { ! 112: return(strcmp((*(struct dirent **)d1)->d_name, ! 113: (*(struct dirent **)d2)->d_name)); ! 114: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.