xref: /PHP-8.4/main/php_scandir.c (revision 01b3fc03)
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