1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
/*
* Copyright 2005-2019 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
*
* Copyright 2005-2010 Ned Ludd - <solar@gentoo.org>
* Copyright 2005-2014 Mike Frysinger - <vapier@gentoo.org>
* Copyright 2018- Fabian Groffen - <grobian@gentoo.org>
*/
#include "main.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <xalloc.h>
#include "scandirat.h"
#if !defined(HAVE_SCANDIRAT)
int
scandirat(int dir_fd, const char *dir, struct dirent ***dirlist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **))
{
int fd;
DIR *dirp;
struct dirent *de, **ret;
size_t retlen = 0;
size_t retsize = 0;
#define INCRSZ 64
/* Cannot use O_PATH as we want to use fdopendir() */
fd = openat(dir_fd, dir, O_RDONLY|O_CLOEXEC);
if (fd == -1)
return -1;
dirp = fdopendir(fd);
if (!dirp) {
close(fd);
return -1;
}
ret = NULL;
while ((de = readdir(dirp))) {
size_t sdesz;
size_t sdenamelen;
if (filter(de) == 0)
continue;
if (retlen == retsize) {
retsize += INCRSZ;
ret = xrealloc(ret, sizeof(*ret) * retsize);
}
sdesz = (void *)de->d_name - (void *)de;
sdenamelen = strlen(de->d_name) + 1;
ret[retlen] = xmalloc(sdesz + sdenamelen);
memcpy(ret[retlen], de, sdesz);
strncpy(ret[retlen]->d_name, de->d_name, sdenamelen);
retlen++;
}
*dirlist = ret;
if (compar != NULL)
qsort(ret, retlen, sizeof(*ret), (void *)compar);
/* closes underlying fd */
closedir(dirp);
return (int)retlen;
}
#endif
void
scandir_free(struct dirent **de, int cnt)
{
if (cnt <= 0)
return;
while (cnt--)
free(de[cnt]);
free(de);
}
int
filter_hidden(const struct dirent *dentry)
{
if (dentry->d_name[0] == '.')
return 0;
return 1;
}
|