Mercurial > pub > dyncall > dyncall
comparison test/dynload_plain/dynload_plain.c @ 308:7c6f19d42b31
dynload UTF-8 support for library paths:
- added missing support to windows
- added test code for all platforms to dynload_plain
- doc update
author | Tassilo Philipp |
---|---|
date | Thu, 24 Oct 2019 23:19:20 +0200 |
parents | f5577f6bf97a |
children | 5b1ff4c73194 |
comparison
equal
deleted
inserted
replaced
307:d2c8ea3ef2ed | 308:7c6f19d42b31 |
---|---|
32 # include <io.h> | 32 # include <io.h> |
33 # define F_OK 0 | 33 # define F_OK 0 |
34 #else | 34 #else |
35 # include <unistd.h> | 35 # include <unistd.h> |
36 #endif | 36 #endif |
37 | |
38 | |
39 int strlen_utf8(const char *s) | |
40 { | |
41 int i=0, j=0; | |
42 while(s[i]) | |
43 j += ((s[i++] & 0xc0) != 0x80); | |
44 return j; | |
45 } | |
37 | 46 |
38 | 47 |
39 int main(int argc, char* argv[]) | 48 int main(int argc, char* argv[]) |
40 { | 49 { |
41 int r = 0, i; | 50 int r = 0, i; |
45 const char* path = NULL; | 54 const char* path = NULL; |
46 /* hacky/lazy list of some clib paths per platform - more/others, like version-suffixed ones */ | 55 /* hacky/lazy list of some clib paths per platform - more/others, like version-suffixed ones */ |
47 /* can be specified in Makefile; this avoids trying to write portable directory traversal stuff */ | 56 /* can be specified in Makefile; this avoids trying to write portable directory traversal stuff */ |
48 const char* clibs[] = { | 57 const char* clibs[] = { |
49 #if defined(DEF_C_DYLIB) | 58 #if defined(DEF_C_DYLIB) |
50 DEF_C_DYLIB, | 59 DEF_C_DYLIB, |
51 #endif | 60 #endif |
52 "/lib/libc.so", | 61 "/lib/libc.so", |
53 "/lib32/libc.so", | 62 "/lib32/libc.so", |
54 "/lib64/libc.so", | 63 "/lib64/libc.so", |
55 "/usr/lib/libc.so", | 64 "/usr/lib/libc.so", |
88 printf("printf at: %p\n", p); | 97 printf("printf at: %p\n", p); |
89 r += (p != NULL); | 98 r += (p != NULL); |
90 | 99 |
91 bs = dlGetLibraryPath(pLib, queriedPath, 200); | 100 bs = dlGetLibraryPath(pLib, queriedPath, 200); |
92 if(bs && bs <= 200) { | 101 if(bs && bs <= 200) { |
93 struct stat st0, st1; /* to check if same file */ | 102 struct stat st0, st1; /* to check if same file */ |
94 int b; | 103 int b, bs_; |
95 printf("path of lib looked up via handle: %s\n", queriedPath); | 104 printf("path of lib looked up via handle: %s\n", queriedPath); |
96 b = (stat(path, &st0) != -1) && (stat(queriedPath, &st1) != -1); | 105 b = (stat(path, &st0) != -1) && (stat(queriedPath, &st1) != -1); |
97 printf("lib (inode:%d) and looked up lib (inode:%d) are same: %d\n", b?st0.st_ino:-1, b?st1.st_ino:-1, b && (st0.st_ino == st1.st_ino)); //@@@ on windows, inode numbers returned here are always 0 | 106 printf("lib (inode:%d) and looked up lib (inode:%d) are same: %d\n", b?st0.st_ino:-1, b?st1.st_ino:-1, b && (st0.st_ino == st1.st_ino)); //@@@ on windows, inode numbers returned here are always 0 |
98 r += b && (st0.st_ino == st1.st_ino); /* compare if same lib using inode */ | 107 r += b && (st0.st_ino == st1.st_ino); /* compare if same lib using inode */ |
99 /*@@@ check if resolved path is absolute*/ | 108 /*@@@ check if resolved path is absolute*/ |
100 | 109 |
101 /* check correct bufsize retval */ | 110 /* check correct bufsize retval */ |
102 b = (bs == strlen(queriedPath) + 1); | 111 b = (bs == strlen(queriedPath) + 1); |
103 printf("looked up path's needed buffer size (%d) computed correctly: %d\n", bs, b); | 112 printf("looked up path's needed buffer size (%d) computed correctly 1/2: %d\n", bs, b); |
113 r += b; | |
114 | |
115 /* check perfect fitting bufsize */ | |
116 queriedPath[0] = 0; | |
117 bs_ = dlGetLibraryPath(pLib, queriedPath, bs); | |
118 b = (bs == bs_ && bs_ == strlen(queriedPath) + 1); | |
119 printf("looked up path's needed buffer size (%d) computed correctly 2/2: %d\n", bs_, b); | |
120 r += b; | |
121 | |
122 /* check if dlGetLibraryPath returns size required if bufsize too small */ | |
123 queriedPath[0] = 0; | |
124 bs_ = dlGetLibraryPath(pLib, queriedPath, 1); /* tiny max buffer size */ | |
125 b = (bs == bs_ && strlen(queriedPath) == 0); /* nothing copied */ | |
126 printf("path lookup size requirement (%d) correctly returned: %d\n", bs_, b); | |
104 r += b; | 127 r += b; |
105 } | 128 } |
106 else | 129 else |
107 printf("failed to query lib path using lib's handle\n"); | 130 printf("failed to query lib path using lib's handle\n"); |
108 | 131 |
109 dlFreeLibrary(pLib); | 132 dlFreeLibrary(pLib); |
133 | |
134 /* check if dlGetLibraryPath returns 0 when trying to lookup dummy */ | |
135 bs = dlGetLibraryPath((DLLib*)1234, queriedPath, 200); | |
136 printf("path lookup failed as expected with bad lib handle: %d\n", bs == 0); | |
137 r += (bs == 0); | |
138 | |
139 /* test UTF-8 path through dummy library that's created by this test's build */ | |
140 { | |
141 static const char* pathU8 = "./dynload_plain_\xc3\x9f_test"; | |
142 int nu8c, b; | |
143 | |
144 //cp(pathU8, "/lib/libz.so.6"); | |
145 pLib = dlLoadLibrary(pathU8); /* check if we can load a lib with a UTF-8 path */ | |
146 printf("pLib (loaded w/ UTF-8 path %s) handle: %p\n", pathU8, pLib); | |
147 r += (p != NULL); | |
148 | |
149 if(pLib) { | |
150 /* get UTF-8 path back */ | |
151 bs = dlGetLibraryPath((DLLib*)pLib, queriedPath, 200); | |
152 if(bs && bs <= 200) { | |
153 nu8c = strlen_utf8(queriedPath); /* num of UTF-8 chars is as big as ... */ | |
154 b = (bs > 0) && (nu8c == bs-2); /* ... buffer size minus 2 (b/c of one 2-byte UTF-8 char and "\0") */ | |
155 printf("UTF-8 path of lib looked up via handle: %s\n", queriedPath); | |
156 printf("looked up UTF-8 path's needed buffer size (%d) for %d UTF-8 char string computed correctly: %d\n", bs, nu8c, b); | |
157 r += b; | |
158 | |
159 dlFreeLibrary(pLib); | |
160 } | |
161 else | |
162 printf("failed to query UTF-8 lib path using lib's handle\n"); | |
163 } | |
164 } | |
110 } | 165 } |
111 else | 166 else |
112 printf("unable to open library %s\n", path); | 167 printf("unable to open library %s\n", path); |
113 | 168 |
114 | 169 |
143 if(pLib) { /* need to lookup by name again, first */ | 198 if(pLib) { /* need to lookup by name again, first */ |
144 p = dlFindSymbol(pLib, "printf"); | 199 p = dlFindSymbol(pLib, "printf"); |
145 name = dlSymsNameFromValue(pSyms, p); | 200 name = dlSymsNameFromValue(pSyms, p); |
146 printf("printf symbol name by its own address (%p): %s\n", p, name?name:""); | 201 printf("printf symbol name by its own address (%p): %s\n", p, name?name:""); |
147 if(name) { | 202 if(name) { |
148 if(strcmp(name, "printf") == 0) | 203 if(strcmp(name, "printf") == 0) |
149 ++r; | 204 ++r; |
150 else { | 205 else { |
151 /* Symbol name returned might be an "alias". In that case, check address again (full lookup to be sure). */ | 206 /* Symbol name returned might be an "alias". In that case, check address again (full lookup to be sure). */ |
152 void* p0 = dlFindSymbol(pLib, name); | 207 void* p0 = dlFindSymbol(pLib, name); |
153 printf("lookup by address returned different name (%s), which is alias of printf: %d\n", name, (p==p0)); | 208 printf("lookup by address returned different name (%s), which is alias of printf: %d\n", name, (p==p0)); |
154 r += (p == p0); | 209 r += (p == p0); |
155 } | 210 } |
156 } | 211 } |
157 dlFreeLibrary(pLib); | 212 dlFreeLibrary(pLib); |
158 } | 213 } |
159 | 214 |
160 dlSymsCleanup(pSyms); | 215 dlSymsCleanup(pSyms); |
161 } | 216 } |
162 else | 217 else |
163 printf("dlSymsInit failed\n"); | 218 printf("dlSymsInit failed\n"); |
164 } | 219 } |
165 | 220 |
166 /* Check final score of right ones to see if all worked */ | 221 /* Check final score of right ones to see if all worked */ |
167 r = (r == 10); | 222 r = (r == 15); |
168 printf("result: dynload_plain: %d\n", r); | 223 printf("result: dynload_plain: %d\n", r); |
169 return !r; | 224 return !r; |
170 } | 225 } |
171 | 226 |