1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Shane Caraveo <shane@caraveo.com> |
16 | Ilia Alshanetsky <ilia@prohost.org> |
17 +----------------------------------------------------------------------+
18 */
19
20 /* $Id$ */
21
22 #include "php.h"
23 #include "php_scandir.h"
24
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
27 #endif
28
29 #ifdef HAVE_DIRENT_H
30 #include <dirent.h>
31 #endif
32
33 #ifndef HAVE_SCANDIR
34
35 #ifdef PHP_WIN32
36 #include "win32/param.h"
37 #include "win32/readdir.h"
38 #endif
39
40 #include <stdlib.h>
41 #include <search.h>
42
43 #endif /* HAVE_SCANDIR */
44
45 #ifndef HAVE_ALPHASORT
46
47 #ifdef HAVE_STRING_H
48 #include <string.h>
49 #endif
50
php_alphasort(const struct dirent ** a,const struct dirent ** b)51 PHPAPI int php_alphasort(const struct dirent **a, const struct dirent **b)
52 {
53 return strcoll((*a)->d_name,(*b)->d_name);
54 }
55 #endif /* HAVE_ALPHASORT */
56
57 #ifndef HAVE_SCANDIR
php_scandir(const char * dirname,struct dirent ** namelist[],int (* selector)(const struct dirent * entry),int (* compare)(const struct dirent ** a,const struct dirent ** b))58 PHPAPI int php_scandir(const char *dirname, struct dirent **namelist[], int (*selector) (const struct dirent *entry), int (*compare) (const struct dirent **a, const struct dirent **b))
59 {
60 DIR *dirp = NULL;
61 struct dirent **vector = NULL;
62 int vector_size = 0;
63 int nfiles = 0;
64 char entry[sizeof(struct dirent)+MAXPATHLEN];
65 struct dirent *dp = (struct dirent *)&entry;
66
67 if (namelist == NULL) {
68 return -1;
69 }
70
71 if (!(dirp = opendir(dirname))) {
72 return -1;
73 }
74
75 while (!php_readdir_r(dirp, (struct dirent *)entry, &dp) && dp) {
76 int dsize = 0;
77 struct dirent *newdp = NULL;
78
79 if (selector && (*selector)(dp) == 0) {
80 continue;
81 }
82
83 if (nfiles == vector_size) {
84 struct dirent **newv;
85 if (vector_size == 0) {
86 vector_size = 10;
87 } else {
88 vector_size *= 2;
89 }
90
91 newv = (struct dirent **) realloc (vector, vector_size * sizeof (struct dirent *));
92 if (!newv) {
93 return -1;
94 }
95 vector = newv;
96 }
97
98 dsize = sizeof (struct dirent) + (((int)strlen(dp->d_name) + 1) * sizeof(char));
99 newdp = (struct dirent *) malloc(dsize);
100
101 if (newdp == NULL) {
102 goto fail;
103 }
104
105 vector[nfiles++] = (struct dirent *) memcpy(newdp, dp, dsize);
106 }
107
108 closedir(dirp);
109
110 *namelist = vector;
111
112 if (compare) {
113 qsort (*namelist, nfiles, sizeof(struct dirent *), (int (*) (const void *, const void *)) compare);
114 }
115
116 return nfiles;
117
118 fail:
119 while (nfiles-- > 0) {
120 free(vector[nfiles]);
121 }
122 free(vector);
123 return -1;
124 }
125 #endif
126
127 /*
128 * Local variables:
129 * tab-width: 4
130 * c-basic-offset: 4
131 * End:
132 * vim600: sw=4 ts=4 fdm=marker
133 * vim<600: sw=4 ts=4
134 */
135