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