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
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18 /*
19 * Copyright (c) 1983 Regents of the University of California.
20 * All rights reserved. The Berkeley software License Agreement
21 * specifies the terms and conditions for redistribution.
22 */
23
24 #pragma ident "%Z%%M% %I% %E% SMI"
25
26 /*
27 * Scan the directory dirname calling select to make a list of selected
28 * directory entries then sort using qsort and compare routine dcomp.
29 * Returns the number of entries and a pointer to a list of pointers to
30 * struct direct (through namelist). Returns -1 if there were any errors.
31 */
32
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/dir.h>
36
37 int
scandir(char * dirname,struct direct * (* namelist[]),int (* select)(),int (* dcomp)())38 scandir(char *dirname, struct direct *(*namelist[]),
39 int (*select)(), int (*dcomp)())
40 {
41 struct direct *d, *p, **names;
42 int nitems;
43 char *cp1, *cp2;
44 struct stat stb;
45 long arraysz;
46 DIR *dirp;
47
48 if ((dirp = opendir(dirname)) == NULL)
49 return (-1);
50 if (fstat(dirp->dd_fd, &stb) < 0)
51 return (-1);
52
53 /*
54 * estimate the array size by taking the size of the directory file
55 * and dividing it by a multiple of the minimum size entry.
56 */
57 arraysz = (stb.st_size / 24);
58 names = (struct direct **)malloc(arraysz * sizeof(struct direct *));
59 if (names == NULL)
60 return (-1);
61
62 nitems = 0;
63 while ((d = readdir(dirp)) != NULL) {
64 if (select != NULL && !(*select)(d))
65 continue; /* just selected names */
66 /*
67 * Make a minimum size copy of the data
68 */
69 p = (struct direct *)malloc(DIRSIZ(d));
70 if (p == NULL)
71 return (-1);
72 p->d_ino = d->d_ino;
73 p->d_reclen = d->d_reclen;
74 p->d_namlen = d->d_namlen;
75 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; );
76 /*
77 * Check to make sure the array has space left and
78 * realloc the maximum size.
79 */
80 if (++nitems >= arraysz) {
81 if (fstat(dirp->dd_fd, &stb) < 0)
82 return (-1); /* just might have grown */
83 arraysz = stb.st_size / 12;
84 names = (struct direct **)realloc((char *)names,
85 arraysz * sizeof(struct direct *));
86 if (names == NULL)
87 return (-1);
88 }
89 names[nitems-1] = p;
90 }
91 closedir(dirp);
92 if (nitems && dcomp != NULL)
93 qsort(names, nitems, sizeof(struct direct *), dcomp);
94 *namelist = names;
95 return (nitems);
96 }
97
98 /*
99 * Alphabetic order comparison routine for those who want it.
100 */
101 int
alphasort(struct direct ** d1,struct direct ** d2)102 alphasort(struct direct **d1, struct direct **d2)
103 {
104 return (strcmp((*d1)->d_name, (*d2)->d_name));
105 }
106