1 /*
2  * Copyright 2014-2016, Björn Ståhl
3  * License: 3-Clause BSD, see COPYING file in arcan source repository.
4  * Reference: http://arcan-fe.com
5  */
6 
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <glob.h>
13 #include <math.h>
14 
15 #include <stdbool.h>
16 #include <sys/types.h>
17 #include <arcan_math.h>
18 #include <arcan_general.h>
19 
arcan_glob(char * basename,enum arcan_namespaces space,void (* cb)(char *,void *),void * tag)20 unsigned arcan_glob(char* basename, enum arcan_namespaces space,
21 	void (*cb)(char*, void*), void* tag)
22 {
23 	unsigned count = 0;
24 
25 	if (!basename || verify_traverse(basename) == NULL)
26 		return 0;
27 
28 /* need to track so that we don't glob namespaces that
29  * happen to collide */
30 	size_t nspaces = (size_t) log2(RESOURCE_SYS_ENDM);
31 
32 	char* globslots[ nspaces ];
33 	memset(globslots, '\0', sizeof(globslots));
34 	size_t ofs = 0;
35 
36 	for (size_t i = 1; i <= RESOURCE_SYS_ENDM; i <<= 1){
37 		if ( (space & i) == 0 )
38 			continue;
39 
40 		glob_t res = {0};
41 		char* path = arcan_expand_resource(basename, i);
42 		bool match = false;
43 
44 		for (size_t j = 0; j < ofs; j++){
45 			if (globslots[ j ] == NULL)
46 				break;
47 
48 			if (strcmp(path, globslots[j]) == 0){
49 				arcan_mem_free(path);
50 				match = true;
51 				break;
52 			}
53 		}
54 
55 		if (match)
56 			continue;
57 
58 		globslots[ofs++] = path;
59 
60 		if ( glob(path, 0, NULL, &res) == 0 ){
61 			char** beg = res.gl_pathv;
62 
63 			while(*beg){
64 				cb(strrchr(*beg, '/') ? strrchr(*beg, '/')+1 : *beg, tag);
65 				beg++;
66 				count++;
67 			}
68 
69 			globfree(&res);
70 		}
71 	}
72 
73 	for (size_t i = 0; i < nspaces && globslots[i] != NULL; i++)
74 		arcan_mem_free(globslots[i]);
75 
76 	return count;
77 }
78 
79