1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 /*LINTLIBRARY*/
41
42 /*
43 * Scan the directory dirname calling select to make a list of selected
44 * directory entries then sort using qsort and compare routine dcomp.
45 * Returns the number of entries and a pointer to a list of pointers to
46 * struct direct (through namelist). Returns -1 if there were any errors.
47 */
48
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/dir.h>
52 #include <errno.h>
53 #include <limits.h>
54 #include <stdlib.h>
55 #include <string.h>
56
57 /*
58 * The macro DIRSIZ(dp) gives an amount of space required to represent
59 * a directory entry. For any directory entry dp->d_reclen >= DIRSIZ(dp).
60 * Specific filesystem types may use this use this macro to construct the value
61 * for d_reclen.
62 */
63 #undef DIRSIZ
64 #define DIRSIZ(dp) \
65 ((sizeof (struct direct) - sizeof ((dp)->d_name) + \
66 (strlen((dp)->d_name)+1) + 3) & ~3)
67
68 #if !defined(_LP64)
69 int
scandir64(char * dirname,struct direct64 * (* namelist[]),int (* select)(struct direct64 *),int (* dcomp)(struct direct64 **,struct direct64 **))70 scandir64(char *dirname, struct direct64 *(*namelist[]),
71 int (*select)(struct direct64 *),
72 int (*dcomp)(struct direct64 **, struct direct64 **))
73 {
74 struct direct64 *d, *p, **names;
75 int nitems;
76 char *cp1, *cp2;
77 struct stat64 stb;
78 long arraysz;
79 DIR *dirp;
80
81 if ((dirp = opendir(dirname)) == NULL)
82 return (-1);
83 if (fstat64(dirp->dd_fd, &stb) < 0)
84 return (-1);
85
86 /*
87 * estimate the array size by taking the size of the directory file
88 * and dividing it by a multiple of the minimum size entry.
89 */
90 arraysz = (stb.st_size / 24);
91 names = (struct direct64 **)malloc(arraysz *
92 sizeof (struct direct64 *));
93 if (names == NULL)
94 return (-1);
95
96 nitems = 0;
97 while ((d = readdir64(dirp)) != NULL) {
98 if (select != NULL && !(*select)(d))
99 continue; /* just selected names */
100 /*
101 * Make a minimum size copy of the data
102 */
103 p = (struct direct64 *)malloc(DIRSIZ64(d));
104 if (p == NULL)
105 return (-1);
106 p->d_ino = d->d_ino;
107 p->d_reclen = d->d_reclen;
108 p->d_namlen = d->d_namlen;
109 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; )
110 ;
111 /*
112 * Check to make sure the array has space left and
113 * realloc the maximum size.
114 */
115 if (++nitems >= arraysz) {
116 if (fstat64(dirp->dd_fd, &stb) < 0)
117 return (-1); /* just might have grown */
118 arraysz = stb.st_size / 12;
119 names = (struct direct64 **)realloc((char *)names,
120 arraysz * sizeof (struct direct64 *));
121 if (names == NULL)
122 return (-1);
123 }
124 names[nitems-1] = p;
125 }
126 (void) closedir(dirp);
127 if (nitems && dcomp != NULL)
128 qsort(names, nitems, sizeof (struct direct64 *),
129 (int(*)(const void *, const void *)) dcomp);
130 *namelist = names;
131 return (nitems);
132 }
133 #endif
134
135
136 int
scandir(char * dirname,struct direct * (* namelist[]),int (* select)(struct direct *),int (* dcomp)(struct direct **,struct direct **))137 scandir(char *dirname, struct direct *(*namelist[]),
138 int (*select)(struct direct *),
139 int (*dcomp)(struct direct **, struct direct **))
140 {
141 struct direct *d, *p, **names;
142 int nitems;
143 char *cp1, *cp2;
144 struct stat64 stb;
145 long arraysz;
146 DIR *dirp;
147
148 if ((dirp = opendir(dirname)) == NULL)
149 return (-1);
150 if (fstat64(dirp->dd_fd, &stb) < 0)
151 return (-1);
152 /*
153 * estimate the array size by taking the size of the directory file
154 * and dividing it by a multiple of the minimum size entry.
155 */
156 if (stb.st_size > SSIZE_MAX) {
157 errno = EOVERFLOW;
158 return (-1);
159 }
160 arraysz = (stb.st_size / 24);
161
162 names = (struct direct **)malloc(arraysz * sizeof (struct direct *));
163 if (names == NULL)
164 return (-1);
165
166 nitems = 0;
167 while ((d = readdir(dirp)) != NULL) {
168 if (select != NULL && !(*select)(d))
169 continue; /* just selected names */
170 /*
171 * Make a minimum size copy of the data
172 */
173 p = (struct direct *)malloc(DIRSIZ(d));
174 if (p == NULL)
175 return (-1);
176 p->d_ino = d->d_ino;
177 p->d_reclen = d->d_reclen;
178 p->d_namlen = d->d_namlen;
179 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; )
180 ;
181 /*
182 * Check to make sure the array has space left and
183 * realloc the maximum size.
184 */
185 if (++nitems >= arraysz) {
186 if (fstat64(dirp->dd_fd, &stb) < 0)
187 return (-1); /* just might have grown */
188 arraysz = stb.st_size / 12;
189 names = (struct direct **)realloc((char *)names,
190 arraysz * sizeof (struct direct *));
191 if (names == NULL)
192 return (-1);
193 }
194 names[nitems-1] = p;
195 }
196 (void) closedir(dirp);
197 if (nitems && dcomp != NULL)
198 qsort(names, nitems, sizeof (struct direct *),
199 (int(*)(const void *, const void *)) dcomp);
200 *namelist = names;
201 return (nitems);
202 }
203
204 /*
205 * Alphabetic order comparison routine for those who want it.
206 */
207 int
alphasort(struct direct ** d1,struct direct ** d2)208 alphasort(struct direct **d1, struct direct **d2)
209 {
210 return (strcmp((*d1)->d_name, (*d2)->d_name));
211 }
212
213 #if !defined(_LP64)
214 int
alphasort64(struct direct64 ** d1,struct direct64 ** d2)215 alphasort64(struct direct64 **d1, struct direct64 **d2)
216 {
217 return (strcmp((*d1)->d_name, (*d2)->d_name));
218 }
219 #endif
220