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