xref: /PHP-7.2/main/php_scandir.c (revision 7a7ec01a)
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