xref: /PHP-7.3/main/php_scandir.c (revision 8d3f8ca1)
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 #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 #ifdef HAVE_STRING_H
46 #include <string.h>
47 #endif
48 
php_alphasort(const struct dirent ** a,const struct dirent ** b)49 PHPAPI int php_alphasort(const struct dirent **a, const struct dirent **b)
50 {
51 	return strcoll((*a)->d_name,(*b)->d_name);
52 }
53 #endif /* HAVE_ALPHASORT */
54 
55 #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))56 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))
57 {
58 	DIR *dirp = NULL;
59 	struct dirent **vector = NULL;
60 	int vector_size = 0;
61 	int nfiles = 0;
62 	char entry[sizeof(struct dirent)+MAXPATHLEN];
63 	struct dirent *dp = (struct dirent *)&entry;
64 
65 	if (namelist == NULL) {
66 		return -1;
67 	}
68 
69 	if (!(dirp = opendir(dirname))) {
70 		return -1;
71 	}
72 
73 	while (!php_readdir_r(dirp, (struct dirent *)entry, &dp) && dp) {
74 		size_t dsize = 0;
75 		struct dirent *newdp = NULL;
76 
77 		if (selector && (*selector)(dp) == 0) {
78 			continue;
79 		}
80 
81 		if (nfiles == vector_size) {
82 			struct dirent **newv;
83 			if (vector_size == 0) {
84 				vector_size = 10;
85 			} else {
86 				vector_size *= 2;
87 			}
88 
89 			newv = (struct dirent **) realloc (vector, vector_size * sizeof (struct dirent *));
90 			if (!newv) {
91 				return -1;
92 			}
93 			vector = newv;
94 		}
95 
96 		dsize = sizeof (struct dirent) + ((strlen(dp->d_name) + 1) * sizeof(char));
97 		newdp = (struct dirent *) malloc(dsize);
98 
99 		if (newdp == NULL) {
100 			goto fail;
101 		}
102 
103 		vector[nfiles++] = (struct dirent *) memcpy(newdp, dp, dsize);
104 	}
105 
106 	closedir(dirp);
107 
108 	*namelist = vector;
109 
110 	if (compare) {
111 		qsort (*namelist, nfiles, sizeof(struct dirent *), (int (*) (const void *, const void *)) compare);
112 	}
113 
114 	return nfiles;
115 
116 fail:
117 	while (nfiles-- > 0) {
118 		free(vector[nfiles]);
119 	}
120 	free(vector);
121 	return -1;
122 }
123 #endif
124 
125 /*
126  * Local variables:
127  * tab-width: 4
128  * c-basic-offset: 4
129  * End:
130  * vim600: sw=4 ts=4 fdm=marker
131  * vim<600: sw=4 ts=4
132  */
133