]> git.zerfleddert.de Git - proxmark3-svn/blob - client/whereami.c
FIX: introduced a bug in luascripts when adding the "safe ascii chars" to ConvertHex...
[proxmark3-svn] / client / whereami.c
1 // (‑●‑●)> released under the WTFPL v2 license, by Gregory Pakosz (@gpakosz)
2 // https://github.com/gpakosz/whereami
3
4 // in case you want to #include "whereami.c" in a larger compilation unit
5 #if !defined(WHEREAMI_H)
6 #include <whereami.h>
7 #endif
8
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12
13 #if defined(__linux__)
14 // make realpath() available:
15 #define _DEFAULT_SOURCE
16 #endif
17
18 #if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
19 #include <stdlib.h>
20 #endif
21
22 #if !defined(WAI_MALLOC)
23 #define WAI_MALLOC(size) malloc(size)
24 #endif
25
26 #if !defined(WAI_FREE)
27 #define WAI_FREE(p) free(p)
28 #endif
29
30 #if !defined(WAI_REALLOC)
31 #define WAI_REALLOC(p, size) realloc(p, size)
32 #endif
33
34 #ifndef WAI_NOINLINE
35 #if defined(_MSC_VER)
36 #define WAI_NOINLINE __declspec(noinline)
37 #elif defined(__GNUC__)
38 #define WAI_NOINLINE __attribute__((noinline))
39 #else
40 #error unsupported compiler
41 #endif
42 #endif
43
44 #if defined(_MSC_VER)
45 #define WAI_RETURN_ADDRESS() _ReturnAddress()
46 #elif defined(__GNUC__)
47 #define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0))
48 #else
49 #error unsupported compiler
50 #endif
51
52 #if defined(_WIN32)
53
54 #define WIN32_LEAN_AND_MEAN
55 #if defined(_MSC_VER)
56 #pragma warning(push, 3)
57 #endif
58 #include <windows.h>
59 #if defined(_MSC_VER)
60 #pragma warning(pop)
61 #endif
62
63 static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
64 {
65 wchar_t buffer1[MAX_PATH];
66 wchar_t buffer2[MAX_PATH];
67 wchar_t* path = NULL;
68 int length = -1;
69
70 for (;;)
71 {
72 DWORD size;
73 int length_, length__;
74
75 size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0]));
76
77 if (size == 0)
78 break;
79 else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0])))
80 {
81 DWORD size_ = size;
82 do
83 {
84 wchar_t* path_;
85
86 path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2);
87 if (!path_)
88 break;
89 size_ *= 2;
90 path = path_;
91 size = GetModuleFileNameW(module, path, size_);
92 }
93 while (size == size_);
94
95 if (size == size_)
96 break;
97 }
98 else
99 path = buffer1;
100
101 if (!_wfullpath(buffer2, path, MAX_PATH))
102 break;
103 length_ = (int)wcslen(buffer2);
104 length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL);
105
106 if (length__ == 0)
107 length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL);
108 if (length__ == 0)
109 break;
110
111 if (length__ <= capacity && dirname_length)
112 {
113 int i;
114
115 for (i = length__ - 1; i >= 0; --i)
116 {
117 if (out[i] == '\\')
118 {
119 *dirname_length = i;
120 break;
121 }
122 }
123 }
124
125 length = length__;
126
127 break;
128 }
129
130 if (path != buffer1)
131 WAI_FREE(path);
132
133 return length;
134 }
135
136 WAI_NOINLINE
137 WAI_FUNCSPEC
138 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
139 {
140 return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length);
141 }
142
143 /*
144 WAI_NOINLINE
145 WAI_FUNCSPEC
146 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
147 {
148 HMODULE module;
149 int length = -1;
150
151 #if defined(_MSC_VER)
152 #pragma warning(push)
153 #pragma warning(disable: 4054)
154 #endif
155 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module))
156 #if defined(_MSC_VER)
157 #pragma warning(pop)
158 #endif
159 {
160 length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length);
161 }
162
163 return length;
164 }
165 */
166
167 #elif defined(__linux__)
168 #include <stdio.h>
169 #include <stdlib.h>
170 #include <string.h>
171 #include <linux/limits.h>
172 #ifndef __STDC_FORMAT_MACROS
173 #define __STDC_FORMAT_MACROS
174 #endif
175 #include <inttypes.h>
176
177 #if !defined(WAI_PROC_SELF_EXE)
178 #define WAI_PROC_SELF_EXE "/proc/self/exe"
179 #endif
180
181 WAI_FUNCSPEC
182 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
183 {
184 char buffer[PATH_MAX];
185 char* resolved = NULL;
186 int length = -1;
187
188 for (;;)
189 {
190 resolved = realpath(WAI_PROC_SELF_EXE, buffer);
191 if (!resolved)
192 break;
193
194 length = (int)strlen(resolved);
195 if (length <= capacity)
196 {
197 memcpy(out, resolved, length);
198
199 if (dirname_length)
200 {
201 int i;
202
203 for (i = length - 1; i >= 0; --i)
204 {
205 if (out[i] == '/')
206 {
207 *dirname_length = i;
208 break;
209 }
210 }
211 }
212 }
213
214 break;
215 }
216
217 return length;
218 }
219
220 #if !defined(WAI_PROC_SELF_MAPS_RETRY)
221 #define WAI_PROC_SELF_MAPS_RETRY 5
222 #endif
223
224 #if !defined(WAI_PROC_SELF_MAPS)
225 #define WAI_PROC_SELF_MAPS "/proc/self/maps"
226 #endif
227
228 #if defined(__ANDROID__) || defined(ANDROID)
229 #include <fcntl.h>
230 #include <sys/mman.h>
231 #endif
232
233 WAI_NOINLINE
234 WAI_FUNCSPEC
235 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
236 {
237 int length = -1;
238 FILE* maps = NULL;
239 int i;
240
241 for (i = 0; i < WAI_PROC_SELF_MAPS_RETRY; ++i)
242 {
243 maps = fopen(WAI_PROC_SELF_MAPS, "r");
244 if (!maps)
245 break;
246
247 for (;;)
248 {
249 char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
250 uint64_t low, high;
251 char perms[5];
252 uint64_t offset;
253 uint32_t major, minor;
254 char path[PATH_MAX];
255 uint32_t inode;
256
257 if (!fgets(buffer, sizeof(buffer), maps))
258 break;
259
260 if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
261 {
262 uint64_t addr = (uint64_t)(uintptr_t)WAI_RETURN_ADDRESS();
263 if (low <= addr && addr <= high)
264 {
265 char* resolved;
266
267 resolved = realpath(path, buffer);
268 if (!resolved)
269 break;
270
271 length = (int)strlen(resolved);
272 #if defined(__ANDROID__) || defined(ANDROID)
273 if (length > 4
274 &&buffer[length - 1] == 'k'
275 &&buffer[length - 2] == 'p'
276 &&buffer[length - 3] == 'a'
277 &&buffer[length - 4] == '.')
278 {
279 int fd = open(path, O_RDONLY);
280 char* begin;
281 char* p;
282
283 begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0);
284 p = begin + offset;
285
286 while (p >= begin) // scan backwards
287 {
288 if (*((uint32_t*)p) == 0x04034b50UL) // local file header found
289 {
290 uint16_t length_ = *((uint16_t*)(p + 26));
291
292 if (length + 2 + length_ < (int)sizeof(buffer))
293 {
294 memcpy(&buffer[length], "!/", 2);
295 memcpy(&buffer[length + 2], p + 30, length_);
296 length += 2 + length_;
297 }
298
299 break;
300 }
301
302 p -= 4;
303 }
304
305 munmap(begin, offset);
306 close(fd);
307 }
308 #endif
309 if (length <= capacity)
310 {
311 memcpy(out, resolved, length);
312
313 if (dirname_length)
314 {
315 int i;
316
317 for (i = length - 1; i >= 0; --i)
318 {
319 if (out[i] == '/')
320 {
321 *dirname_length = i;
322 break;
323 }
324 }
325 }
326 }
327
328 break;
329 }
330 }
331 }
332
333 fclose(maps);
334
335 if (length != -1)
336 break;
337 }
338
339 return length;
340 }
341
342 #elif defined(__APPLE__)
343
344 #define _DARWIN_BETTER_REALPATH
345 #include <mach-o/dyld.h>
346 #include <limits.h>
347 #include <stdlib.h>
348 #include <string.h>
349 #include <dlfcn.h>
350
351 WAI_FUNCSPEC
352 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
353 {
354 char buffer1[PATH_MAX];
355 char buffer2[PATH_MAX];
356 char* path = buffer1;
357 char* resolved = NULL;
358 int length = -1;
359
360 for (;;)
361 {
362 uint32_t size = (uint32_t)sizeof(buffer1);
363 if (_NSGetExecutablePath(path, &size) == -1)
364 {
365 path = (char*)WAI_MALLOC(size);
366 if (!_NSGetExecutablePath(path, &size))
367 break;
368 }
369
370 resolved = realpath(path, buffer2);
371 if (!resolved)
372 break;
373
374 length = (int)strlen(resolved);
375 if (length <= capacity)
376 {
377 memcpy(out, resolved, length);
378
379 if (dirname_length)
380 {
381 int i;
382
383 for (i = length - 1; i >= 0; --i)
384 {
385 if (out[i] == '/')
386 {
387 *dirname_length = i;
388 break;
389 }
390 }
391 }
392 }
393
394 break;
395 }
396
397 if (path != buffer1)
398 WAI_FREE(path);
399
400 return length;
401 }
402
403 WAI_NOINLINE
404 WAI_FUNCSPEC
405 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
406 {
407 char buffer[PATH_MAX];
408 char* resolved = NULL;
409 int length = -1;
410
411 for(;;)
412 {
413 Dl_info info;
414
415 if (dladdr(WAI_RETURN_ADDRESS(), &info))
416 {
417 resolved = realpath(info.dli_fname, buffer);
418 if (!resolved)
419 break;
420
421 length = (int)strlen(resolved);
422 if (length <= capacity)
423 {
424 memcpy(out, resolved, length);
425
426 if (dirname_length)
427 {
428 int i;
429
430 for (i = length - 1; i >= 0; --i)
431 {
432 if (out[i] == '/')
433 {
434 *dirname_length = i;
435 break;
436 }
437 }
438 }
439 }
440 }
441
442 break;
443 }
444
445 return length;
446 }
447
448 #elif defined(__QNXNTO__)
449
450 #include <limits.h>
451 #include <stdio.h>
452 #include <stdlib.h>
453 #include <string.h>
454 #include <dlfcn.h>
455
456 #if !defined(WAI_PROC_SELF_EXE)
457 #define WAI_PROC_SELF_EXE "/proc/self/exefile"
458 #endif
459
460 WAI_FUNCSPEC
461 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
462 {
463 char buffer1[PATH_MAX];
464 char buffer2[PATH_MAX];
465 char* resolved = NULL;
466 FILE* self_exe = NULL;
467 int length = -1;
468
469 for (;;)
470 {
471 self_exe = fopen(WAI_PROC_SELF_EXE, "r");
472 if (!self_exe)
473 break;
474
475 if (!fgets(buffer1, sizeof(buffer1), self_exe))
476 break;
477
478 resolved = realpath(buffer1, buffer2);
479 if (!resolved)
480 break;
481
482 length = (int)strlen(resolved);
483 if (length <= capacity)
484 {
485 memcpy(out, resolved, length);
486
487 if (dirname_length)
488 {
489 int i;
490
491 for (i = length - 1; i >= 0; --i)
492 {
493 if (out[i] == '/')
494 {
495 *dirname_length = i;
496 break;
497 }
498 }
499 }
500 }
501
502 break;
503 }
504
505 fclose(self_exe);
506
507 return length;
508 }
509
510 WAI_FUNCSPEC
511 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
512 {
513 char buffer[PATH_MAX];
514 char* resolved = NULL;
515 int length = -1;
516
517 for(;;)
518 {
519 Dl_info info;
520
521 if (dladdr(WAI_RETURN_ADDRESS(), &info))
522 {
523 resolved = realpath(info.dli_fname, buffer);
524 if (!resolved)
525 break;
526
527 length = (int)strlen(resolved);
528 if (length <= capacity)
529 {
530 memcpy(out, resolved, length);
531
532 if (dirname_length)
533 {
534 int i;
535
536 for (i = length - 1; i >= 0; --i)
537 {
538 if (out[i] == '/')
539 {
540 *dirname_length = i;
541 break;
542 }
543 }
544 }
545 }
546 }
547
548 break;
549 }
550
551 return length;
552 }
553
554 #elif defined(__DragonFly__) || defined(__FreeBSD__) || \
555 defined(__FreeBSD_kernel__) || defined(__NetBSD__)
556
557 #include <limits.h>
558 #include <stdlib.h>
559 #include <string.h>
560 #include <sys/types.h>
561 #include <sys/sysctl.h>
562 #include <dlfcn.h>
563
564 WAI_FUNCSPEC
565 int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
566 {
567 char buffer1[PATH_MAX];
568 char buffer2[PATH_MAX];
569 char* path = buffer1;
570 char* resolved = NULL;
571 int length = -1;
572
573 for (;;)
574 {
575 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
576 size_t size = sizeof(buffer1);
577
578 if (sysctl(mib, (u_int)(sizeof(mib) / sizeof(mib[0])), path, &size, NULL, 0) != 0)
579 break;
580
581 resolved = realpath(path, buffer2);
582 if (!resolved)
583 break;
584
585 length = (int)strlen(resolved);
586 if (length <= capacity)
587 {
588 memcpy(out, resolved, length);
589
590 if (dirname_length)
591 {
592 int i;
593
594 for (i = length - 1; i >= 0; --i)
595 {
596 if (out[i] == '/')
597 {
598 *dirname_length = i;
599 break;
600 }
601 }
602 }
603 }
604
605 break;
606 }
607
608 if (path != buffer1)
609 WAI_FREE(path);
610
611 return length;
612 }
613
614 WAI_NOINLINE
615 WAI_FUNCSPEC
616 int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
617 {
618 char buffer[PATH_MAX];
619 char* resolved = NULL;
620 int length = -1;
621
622 for(;;)
623 {
624 Dl_info info;
625
626 if (dladdr(WAI_RETURN_ADDRESS(), &info))
627 {
628 resolved = realpath(info.dli_fname, buffer);
629 if (!resolved)
630 break;
631
632 length = (int)strlen(resolved);
633 if (length <= capacity)
634 {
635 memcpy(out, resolved, length);
636
637 if (dirname_length)
638 {
639 int i;
640
641 for (i = length - 1; i >= 0; --i)
642 {
643 if (out[i] == '/')
644 {
645 *dirname_length = i;
646 break;
647 }
648 }
649 }
650 }
651 }
652
653 break;
654 }
655
656 return length;
657 }
658
659 #else
660
661 #error unsupported platform
662
663 #endif
664
665 #ifdef __cplusplus
666 }
667 #endif
Impressum, Datenschutz