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