date and time created 82/12/13 10:43:38 by ralph
[unix-history] / usr / src / lib / libc / gen / scandir.c
CommitLineData
38cb3a9a
RC
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
13scandir(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 */
75alphasort(d1, d2)
76 struct direct **d1, **d2;
77{
78 return(strcmp((*d1)->d_name, (*d2)->d_name));
79}