dyld-750.5.tar.gz
[apple/dyld.git] / testing / test-cases / shared_cache_iterate.dtest / main.c
1
2 // BUILD: $CC main.c -o $BUILD_DIR/shared_cache_iterate.exe
3
4 // RUN: ./shared_cache_iterate.exe
5
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <mach-o/dyld_priv.h>
11 #include <dlfcn.h>
12 #include <sys/syslimits.h>
13 #include <dirent.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16
17 #if __has_feature(ptrauth_calls)
18 #include <ptrauth.h>
19 #endif
20
21 #include "test_support.h"
22
23 struct dyld_cache_header
24 {
25 char magic[16];
26 uint64_t other[9];
27 uuid_t uuid;
28 };
29
30 static void forEachCacheInDir(const char* dirPath, void (^handler)(const uuid_t uuid))
31 {
32 DIR* dirp = opendir(dirPath);
33 if ( dirp != NULL) {
34 struct dirent entry;
35 struct dirent* entp = NULL;
36 char cachePath[PATH_MAX];
37 while ( readdir_r(dirp, &entry, &entp) == 0 ) {
38 if ( entp == NULL )
39 break;
40 if ( entp->d_type != DT_REG )
41 continue;
42 if ( strlcpy(cachePath, dirPath, PATH_MAX) >= PATH_MAX )
43 continue;
44 if ( strlcat(cachePath, "/", PATH_MAX) >= PATH_MAX )
45 continue;
46 if ( strlcat(cachePath, entp->d_name, PATH_MAX) >= PATH_MAX )
47 continue;
48 int fd = open(cachePath, O_RDONLY);
49 if ( fd < 0 )
50 continue;
51 struct dyld_cache_header cacheHeader;
52 ssize_t amount = pread(fd, &cacheHeader, sizeof(cacheHeader), 0);
53 close(fd);
54 if ( amount != sizeof(cacheHeader) )
55 continue;
56 if ( memcmp(cacheHeader.magic, "dyld_v", 6) == 0 )
57 handler(cacheHeader.uuid);
58 }
59 closedir(dirp);
60 }
61 }
62
63
64 int main(int argc, const char* argv[], const char* envp[], const char* apple[]) {
65 size_t cacheLen;
66 const void* cacheStart = _dyld_get_shared_cache_range(&cacheLen);
67 uuid_t currentCacheUUID;
68 if ( _dyld_get_shared_cache_uuid(currentCacheUUID) ) {
69 const uint8_t* currentCacheUUIDptr = currentCacheUUID;
70 // have dyld cache
71 __block unsigned count = 0;
72 __block bool badVersion = false;
73 // iterate current cache
74 int result = dyld_shared_cache_iterate_text(currentCacheUUID, ^(const dyld_shared_cache_dylib_text_info* info) {
75 if ( info->version != 2 )
76 badVersion = true;
77 ++count;
78 });
79 if ( result != 0 ) {
80 FAIL("dyld_shared_cache_iterate_text() returned non-zero: %d", result);
81 }
82 if ( count < 100 ) {
83 FAIL("dyld_shared_cache_iterate_text() iterated over less than 100 images: %d", count);
84 }
85 if ( badVersion ) {
86 FAIL("dyld_shared_cache_iterate_text() some dyld_shared_cache_dylib_text_info was not 2");
87 }
88
89 // iterate current cache
90 count = 0;
91 const char* extraSearchDirsStorage[] = { "/tmp/", NULL };
92 const char** extraSearchDirs = extraSearchDirsStorage;
93 result = dyld_shared_cache_find_iterate_text(currentCacheUUID, extraSearchDirs, ^(const dyld_shared_cache_dylib_text_info* info) {
94 if ( info->version != 2 )
95 badVersion = true;
96 ++count;
97 });
98 if ( result != 0 ) {
99 FAIL("dyld_shared_cache_find_iterate_text() returned non-zero: %d", result);
100 }
101 if ( count < 100 ) {
102 FAIL("dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d", count);
103 }
104 if ( badVersion ) {
105 FAIL("dyld_shared_cache_find_iterate_text() some dyld_shared_cache_dylib_text_info was not 2");
106 }
107
108 // look for non-existent cache
109 count = 0;
110 uuid_t badCacheUUID;
111 bzero(&badCacheUUID, sizeof(uuid_t));
112 badCacheUUID[1] = 0x33;
113 result = dyld_shared_cache_find_iterate_text(badCacheUUID, extraSearchDirs, ^(const dyld_shared_cache_dylib_text_info* info) {
114 ++count;
115 });
116 if ( result == 0 ) {
117 FAIL("dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d", result);
118 }
119 if ( count != 0 ) {
120 FAIL("dyld_shared_cache_find_iterate_text() expected iteration count is zero: %d", count);
121 }
122
123 // find other cache
124 const char* curCachePath = dyld_shared_cache_file_path();
125 if ( curCachePath == NULL ) {
126 FAIL("dyld_shared_cache_file_path() returned NULL");
127 }
128 char cacheDir[PATH_MAX];
129 strlcpy(cacheDir, curCachePath, PATH_MAX);
130 char* end = strrchr(cacheDir, '/');
131 if ( end == NULL ) {
132 FAIL("cache path has no '/'");
133 }
134 *end = '\0';
135 forEachCacheInDir(cacheDir, ^(const uuid_t uuid) {
136 if ( uuid_compare(uuid, currentCacheUUIDptr) != 0 ) {
137 count = 0;
138 int res = dyld_shared_cache_find_iterate_text(uuid, extraSearchDirs, ^(const dyld_shared_cache_dylib_text_info* info) {
139 ++count;
140 });
141 if ( res != 0 ) {
142 FAIL("dyld_shared_cache_find_iterate_text() expected result to be nonzero: %d", result);
143 }
144 if ( count < 100 ) {
145 FAIL("dyld_shared_cache_find_iterate_text() iterated over less than 100 images: %d", count);
146 }
147 }
148 });
149 }
150 else {
151 LOG("no dyld cache");
152 }
153
154 PASS("Success");
155 }
156
157