Blame


1 11c98667 2021-04-25 op /* $OpenBSD: scandir.c,v 1.21 2019/06/28 13:32:41 deraadt Exp $ */
2 11c98667 2021-04-25 op
3 11c98667 2021-04-25 op /*
4 11c98667 2021-04-25 op * This is a modified verision of scandir that takes an explicit
5 11c98667 2021-04-25 op * directory file descriptor as parameter.
6 11c98667 2021-04-25 op */
7 11c98667 2021-04-25 op
8 11c98667 2021-04-25 op /*
9 11c98667 2021-04-25 op * Copyright (c) 1983, 1993
10 11c98667 2021-04-25 op * The Regents of the University of California. All rights reserved.
11 11c98667 2021-04-25 op *
12 11c98667 2021-04-25 op * Redistribution and use in source and binary forms, with or without
13 11c98667 2021-04-25 op * modification, are permitted provided that the following conditions
14 11c98667 2021-04-25 op * are met:
15 11c98667 2021-04-25 op * 1. Redistributions of source code must retain the above copyright
16 11c98667 2021-04-25 op * notice, this list of conditions and the following disclaimer.
17 11c98667 2021-04-25 op * 2. Redistributions in binary form must reproduce the above copyright
18 11c98667 2021-04-25 op * notice, this list of conditions and the following disclaimer in the
19 11c98667 2021-04-25 op * documentation and/or other materials provided with the distribution.
20 11c98667 2021-04-25 op * 3. Neither the name of the University nor the names of its contributors
21 11c98667 2021-04-25 op * may be used to endorse or promote products derived from this software
22 11c98667 2021-04-25 op * without specific prior written permission.
23 11c98667 2021-04-25 op *
24 11c98667 2021-04-25 op * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 11c98667 2021-04-25 op * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 11c98667 2021-04-25 op * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 11c98667 2021-04-25 op * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 11c98667 2021-04-25 op * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 11c98667 2021-04-25 op * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 11c98667 2021-04-25 op * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 11c98667 2021-04-25 op * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 11c98667 2021-04-25 op * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 11c98667 2021-04-25 op * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 11c98667 2021-04-25 op * SUCH DAMAGE.
35 11c98667 2021-04-25 op */
36 11c98667 2021-04-25 op
37 11c98667 2021-04-25 op /*
38 11c98667 2021-04-25 op * Scan the directory fd calling select to make a list of selected
39 11c98667 2021-04-25 op * directory entries then sort using qsort and compare routine dcomp.
40 11c98667 2021-04-25 op * Returns the number of entries and a pointer to a list of pointers to
41 11c98667 2021-04-25 op * struct dirent (through namelist). Returns -1 if there were any errors.
42 11c98667 2021-04-25 op */
43 11c98667 2021-04-25 op
44 11c98667 2021-04-25 op #include "gmid.h"
45 11c98667 2021-04-25 op
46 11c98667 2021-04-25 op #include <sys/types.h>
47 11c98667 2021-04-25 op #include <sys/stat.h>
48 11c98667 2021-04-25 op
49 11c98667 2021-04-25 op #include <dirent.h>
50 11c98667 2021-04-25 op #include <errno.h>
51 11c98667 2021-04-25 op #include <stdint.h>
52 11c98667 2021-04-25 op #include <stdlib.h>
53 11c98667 2021-04-25 op #include <string.h>
54 11c98667 2021-04-25 op
55 11c98667 2021-04-25 op #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
56 11c98667 2021-04-25 op
57 11c98667 2021-04-25 op /*
58 11c98667 2021-04-25 op * The DIRSIZ macro is the minimum record length which will hold the directory
59 11c98667 2021-04-25 op * entry. This requires the amount of space in struct dirent without the
60 11c98667 2021-04-25 op * d_name field, plus enough space for the name and a terminating nul byte
61 11c98667 2021-04-25 op * (dp->d_namlen + 1), rounded up to a 4 byte boundary.
62 11c98667 2021-04-25 op */
63 11c98667 2021-04-25 op #undef DIRSIZ
64 5aba6395 2021-04-25 op #define DIRSIZ(dp, namlen) \
65 11c98667 2021-04-25 op ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
66 5aba6395 2021-04-25 op ((namlen + 1 + 3) &~ 3))
67 11c98667 2021-04-25 op
68 11c98667 2021-04-25 op int
69 11c98667 2021-04-25 op scandir_fd(int fd, struct dirent ***namelist,
70 11c98667 2021-04-25 op int (*select)(const struct dirent *),
71 11c98667 2021-04-25 op int (*dcomp)(const struct dirent **, const struct dirent **))
72 11c98667 2021-04-25 op {
73 11c98667 2021-04-25 op struct dirent *d, *p, **names = NULL;
74 5aba6395 2021-04-25 op size_t arraysz, namlen, nitems = 0;
75 11c98667 2021-04-25 op struct stat stb;
76 11c98667 2021-04-25 op DIR *dirp;
77 11c98667 2021-04-25 op
78 11c98667 2021-04-25 op if ((dirp = fdopendir(fd)) == NULL)
79 11c98667 2021-04-25 op return (-1);
80 11c98667 2021-04-25 op if (fstat(fd, &stb) == -1)
81 11c98667 2021-04-25 op goto fail;
82 11c98667 2021-04-25 op
83 11c98667 2021-04-25 op /*
84 11c98667 2021-04-25 op * estimate the array size by taking the size of the directory file
85 11c98667 2021-04-25 op * and dividing it by a multiple of the minimum size entry.
86 11c98667 2021-04-25 op */
87 11c98667 2021-04-25 op arraysz = MAXIMUM(stb.st_size / 24, 16);
88 11c98667 2021-04-25 op if (arraysz > SIZE_MAX / sizeof(struct dirent *)) {
89 11c98667 2021-04-25 op errno = ENOMEM;
90 11c98667 2021-04-25 op goto fail;
91 11c98667 2021-04-25 op }
92 11c98667 2021-04-25 op names = calloc(arraysz, sizeof(struct dirent *));
93 11c98667 2021-04-25 op if (names == NULL)
94 11c98667 2021-04-25 op goto fail;
95 11c98667 2021-04-25 op
96 11c98667 2021-04-25 op while ((d = readdir(dirp)) != NULL) {
97 11c98667 2021-04-25 op if (select != NULL && !(*select)(d))
98 11c98667 2021-04-25 op continue; /* just selected names */
99 11c98667 2021-04-25 op
100 11c98667 2021-04-25 op /*
101 11c98667 2021-04-25 op * Check to make sure the array has space left and
102 11c98667 2021-04-25 op * realloc the maximum size.
103 11c98667 2021-04-25 op */
104 11c98667 2021-04-25 op if (nitems >= arraysz) {
105 11c98667 2021-04-25 op struct dirent **nnames;
106 11c98667 2021-04-25 op
107 11c98667 2021-04-25 op if (fstat(fd, &stb) == -1)
108 11c98667 2021-04-25 op goto fail;
109 11c98667 2021-04-25 op
110 11c98667 2021-04-25 op arraysz *= 2;
111 11c98667 2021-04-25 op if (SIZE_MAX / sizeof(struct dirent *) < arraysz)
112 11c98667 2021-04-25 op goto fail;
113 11c98667 2021-04-25 op nnames = reallocarray(names,
114 11c98667 2021-04-25 op arraysz, sizeof(struct dirent *));
115 11c98667 2021-04-25 op if (nnames == NULL)
116 11c98667 2021-04-25 op goto fail;
117 11c98667 2021-04-25 op
118 11c98667 2021-04-25 op names = nnames;
119 11c98667 2021-04-25 op }
120 11c98667 2021-04-25 op
121 11c98667 2021-04-25 op /*
122 11c98667 2021-04-25 op * Make a minimum size copy of the data
123 11c98667 2021-04-25 op */
124 5aba6395 2021-04-25 op namlen = strlen(d->d_name);
125 5aba6395 2021-04-25 op p = malloc(DIRSIZ(d, namlen));
126 11c98667 2021-04-25 op if (p == NULL)
127 11c98667 2021-04-25 op goto fail;
128 11c98667 2021-04-25 op
129 11c98667 2021-04-25 op p->d_ino = d->d_ino;
130 11c98667 2021-04-25 op p->d_type = d->d_type;
131 11c98667 2021-04-25 op p->d_reclen = d->d_reclen;
132 b5fdc32e 2021-04-25 op memcpy(p->d_name, d->d_name, namlen + 1);
133 11c98667 2021-04-25 op names[nitems++] = p;
134 11c98667 2021-04-25 op }
135 11c98667 2021-04-25 op closedir(dirp);
136 11c98667 2021-04-25 op if (nitems && dcomp != NULL)
137 11c98667 2021-04-25 op qsort(names, nitems, sizeof(struct dirent *),
138 11c98667 2021-04-25 op (int(*)(const void *, const void *))dcomp);
139 11c98667 2021-04-25 op *namelist = names;
140 11c98667 2021-04-25 op return (nitems);
141 11c98667 2021-04-25 op
142 11c98667 2021-04-25 op fail:
143 11c98667 2021-04-25 op while (nitems > 0)
144 11c98667 2021-04-25 op free(names[--nitems]);
145 11c98667 2021-04-25 op free(names);
146 11c98667 2021-04-25 op closedir(dirp);
147 11c98667 2021-04-25 op return (-1);
148 11c98667 2021-04-25 op }
149 11c98667 2021-04-25 op
150 11c98667 2021-04-25 op int
151 11c98667 2021-04-25 op select_non_dot(const struct dirent *d)
152 11c98667 2021-04-25 op {
153 11c98667 2021-04-25 op return strcmp(d->d_name, ".");
154 11c98667 2021-04-25 op }
155 11c98667 2021-04-25 op
156 11c98667 2021-04-25 op int
157 11c98667 2021-04-25 op select_non_dotdot(const struct dirent *d)
158 11c98667 2021-04-25 op {
159 11c98667 2021-04-25 op return strcmp(d->d_name, ".") && strcmp(d->d_name, "..");
160 11c98667 2021-04-25 op }