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