|
|
1.1 root 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 provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #if defined(LIBC_SCCS) && !defined(lint)
21: static char sccsid[] = "@(#)scandir.c 5.9 (Berkeley) 6/24/90";
22: #endif /* LIBC_SCCS and not lint */
23:
24: /*
25: * Scan the directory dirname calling select to make a list of selected
26: * directory entries then sort using qsort and compare routine dcomp.
27: * Returns the number of entries and a pointer to a list of pointers to
28: * struct dirent (through namelist). Returns -1 if there were any errors.
29: */
30:
31: #include <sys/types.h>
32: #include <sys/stat.h>
33: #include <dirent.h>
34:
35: /*
36: * The DIRSIZ macro gives the minimum record length which will hold
37: * the directory entry. This requires the amount of space in struct dirent
38: * without the d_name field, plus enough space for the name with a terminating
39: * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
40: */
41: #undef DIRSIZ
42: #define DIRSIZ(dp) \
43: ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
44:
45: scandir(dirname, namelist, select, dcomp)
46: char *dirname;
47: struct dirent ***namelist;
48: int (*select)(), (*dcomp)();
49: {
50: register struct dirent *d, *p, **names;
51: register int nitems;
52: struct stat stb;
53: long arraysz;
54: DIR *dirp;
55:
56: if ((dirp = opendir(dirname)) == NULL)
57: return(-1);
58: if (fstat(dirp->dd_fd, &stb) < 0)
59: return(-1);
60:
61: /*
62: * estimate the array size by taking the size of the directory file
63: * and dividing it by a multiple of the minimum size entry.
64: */
65: arraysz = (stb.st_size / 24);
66: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
67: if (names == NULL)
68: return(-1);
69:
70: nitems = 0;
71: while ((d = readdir(dirp)) != NULL) {
72: if (select != NULL && !(*select)(d))
73: continue; /* just selected names */
74: /*
75: * Make a minimum size copy of the data
76: */
77: p = (struct dirent *)malloc(DIRSIZ(d));
78: if (p == NULL)
79: return(-1);
80: p->d_ino = d->d_ino;
81: p->d_reclen = d->d_reclen;
82: p->d_namlen = d->d_namlen;
83: bcopy(d->d_name, p->d_name, p->d_namlen + 1);
84: /*
85: * Check to make sure the array has space left and
86: * realloc the maximum size.
87: */
88: if (++nitems >= arraysz) {
89: if (fstat(dirp->dd_fd, &stb) < 0)
90: return(-1); /* just might have grown */
91: arraysz = stb.st_size / 12;
92: names = (struct dirent **)realloc((char *)names,
93: arraysz * sizeof(struct dirent *));
94: if (names == NULL)
95: return(-1);
96: }
97: names[nitems-1] = p;
98: }
99: closedir(dirp);
100: if (nitems && dcomp != NULL)
101: qsort(names, nitems, sizeof(struct dirent *), dcomp);
102: *namelist = names;
103: return(nitems);
104: }
105:
106: /*
107: * Alphabetic order comparison routine for those who want it.
108: */
109: alphasort(d1, d2)
110: void *d1, *d2;
111: {
112: return(strcmp((*(struct dirent **)d1)->d_name,
113: (*(struct dirent **)d2)->d_name));
114: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.