1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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 #include "php.h"
21 #include "php_scandir.h"
22
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26
27 #ifdef HAVE_DIRENT_H
28 #include <dirent.h>
29 #endif
30
31 #ifndef HAVE_SCANDIR
32
33 #ifdef PHP_WIN32
34 #include "win32/param.h"
35 #include "win32/readdir.h"
36 #endif
37
38 #include <stdlib.h>
39 #include <search.h>
40
41 #endif /* HAVE_SCANDIR */
42
43 #ifndef HAVE_ALPHASORT
44
45 #include <string.h>
46
php_alphasort(const struct dirent ** a,const struct dirent ** b)47 PHPAPI int php_alphasort(const struct dirent **a, const struct dirent **b)
48 {
49 return strcoll((*a)->d_name,(*b)->d_name);
50 }
51 #endif /* HAVE_ALPHASORT */
52
53 #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))54 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))
55 {
56 DIR *dirp = NULL;
57 struct dirent **vector = NULL;
58 int vector_size = 0;
59 int nfiles = 0;
60 struct dirent *dp;
61
62 if (namelist == NULL) {
63 return -1;
64 }
65
66 if (!(dirp = opendir(dirname))) {
67 return -1;
68 }
69
70 while ((dp = readdir(dirp))) {
71 size_t dsize = 0;
72 struct dirent *newdp = NULL;
73
74 if (selector && (*selector)(dp) == 0) {
75 continue;
76 }
77
78 if (nfiles == vector_size) {
79 struct dirent **newv;
80 if (vector_size == 0) {
81 vector_size = 10;
82 } else {
83 vector_size *= 2;
84 }
85
86 newv = (struct dirent **) realloc (vector, vector_size * sizeof (struct dirent *));
87 if (!newv) {
88 return -1;
89 }
90 vector = newv;
91 }
92
93 dsize = sizeof (struct dirent) + ((strlen(dp->d_name) + 1) * sizeof(char));
94 newdp = (struct dirent *) malloc(dsize);
95
96 if (newdp == NULL) {
97 goto fail;
98 }
99
100 vector[nfiles++] = (struct dirent *) memcpy(newdp, dp, dsize);
101 }
102
103 closedir(dirp);
104
105 *namelist = vector;
106
107 if (compare) {
108 qsort (*namelist, nfiles, sizeof(struct dirent *), (int (*) (const void *, const void *)) compare);
109 }
110
111 return nfiles;
112
113 fail:
114 while (nfiles-- > 0) {
115 free(vector[nfiles]);
116 }
117 free(vector);
118 return -1;
119 }
120 #endif
121