1 #ifndef lint 2 static char sccsid[] = "@(#)scandir.c 4.2 (Berkeley) 07/01/83"; 3 #endif 4 5 /* 6 * Scan the directory dirname calling select to make a list of selected 7 * directory entries then sort using qsort and compare routine dcomp. 8 * Returns the number of entries and a pointer to a list of pointers to 9 * struct direct (through namelist). Returns -1 if there were any errors. 10 */ 11 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 #include <sys/dir.h> 15 16 scandir(dirname, namelist, select, dcomp) 17 char *dirname; 18 struct direct *(*namelist[]); 19 int (*select)(), (*dcomp)(); 20 { 21 register struct direct *d, *p, **names; 22 register int nitems; 23 register char *cp1, *cp2; 24 struct stat stb; 25 long arraysz; 26 DIR *dirp; 27 28 if ((dirp = opendir(dirname)) == NULL) 29 return(-1); 30 if (fstat(dirp->dd_fd, &stb) < 0) 31 return(-1); 32 33 /* 34 * estimate the array size by taking the size of the directory file 35 * and dividing it by a multiple of the minimum size entry. 36 */ 37 arraysz = (stb.st_size / 24); 38 names = (struct direct **)malloc(arraysz * sizeof(struct direct *)); 39 if (names == NULL) 40 return(-1); 41 42 nitems = 0; 43 while ((d = readdir(dirp)) != NULL) { 44 if (select != NULL && !(*select)(d)) 45 continue; /* just selected names */ 46 /* 47 * Make a minimum size copy of the data 48 */ 49 p = (struct direct *)malloc(DIRSIZ(d)); 50 if (p == NULL) 51 return(-1); 52 p->d_ino = d->d_ino; 53 p->d_reclen = d->d_reclen; 54 p->d_namlen = d->d_namlen; 55 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; ); 56 /* 57 * Check to make sure the array has space left and 58 * realloc the maximum size. 59 */ 60 if (++nitems >= arraysz) { 61 names = (struct direct **)realloc((char *)names, 62 (stb.st_size/12) * sizeof(struct direct *)); 63 if (names == NULL) 64 return(-1); 65 } 66 names[nitems-1] = p; 67 } 68 closedir(dirp); 69 if (nitems && dcomp != NULL) 70 qsort(names, nitems, sizeof(struct direct *), dcomp); 71 *namelist = names; 72 return(nitems); 73 } 74 75 /* 76 * Alphabetic order comparison routine for those who want it. 77 */ 78 alphasort(d1, d2) 79 struct direct **d1, **d2; 80 { 81 return(strcmp((*d1)->d_name, (*d2)->d_name)); 82 } 83