10#include "nuitka/prelude.h"
13#if defined(__FreeBSD__) || defined(__OpenBSD__)
14#include <sys/sysctl.h>
33#include <mach-o/dyld.h>
38#define Py_MIN(x, y) (((x) > (y)) ? (y) : (x))
41#include "nuitka/environment_variables_system.h"
42#include "nuitka/filesystem_paths.h"
43#include "nuitka/safe_string_ops.h"
45#if _NUITKA_DLL_MODE || _NUITKA_MODULE_MODE
46static filename_char_t
const *_pseudo_dll_filename = NULL;
48void setDllFilename(filename_char_t
const *filename) { _pseudo_dll_filename = filename; }
52void normalizePath(filename_char_t *filename) {
53 filename_char_t *w = filename;
57 if (*w == FILENAME_SEP_CHAR) {
58 while (*(w + 1) == FILENAME_SEP_CHAR) {
59 filename_char_t *f = w;
82static wchar_t *stripFilenameW(
wchar_t *path) {
83 wchar_t *last_slash = NULL;
93 if (last_slash != NULL) {
100filename_char_t *stripBaseFilename(filename_char_t
const *filename) {
101 static wchar_t result[MAXPATHLEN + 1];
103 copyStringSafeW(result, filename,
sizeof(result) /
sizeof(
wchar_t));
104 stripFilenameW(result);
109filename_char_t *stripBaseFilename(filename_char_t
const *filename) {
110 static char result[MAXPATHLEN + 1];
111 copyStringSafe(result, filename,
sizeof(result));
113 return dirname(result);
118static void makeShortFilename(
wchar_t *filename,
size_t buffer_size) {
119#ifndef _NUITKA_EXPERIMENTAL_AVOID_SHORT_PATH
121 DWORD length = GetShortPathNameW(filename, NULL, 0);
126 wchar_t *short_filename = (
wchar_t *)malloc((length + 1) *
sizeof(wchar_t));
127 DWORD res = GetShortPathNameW(filename, short_filename, length);
130 if (unlikely(res > length)) {
135 appendWStringSafeW(filename, short_filename, buffer_size);
137 free(short_filename);
141static void makeShortDirFilename(
wchar_t *filename,
size_t buffer_size) {
142 wchar_t *changed = stripFilenameW(filename);
143 if (changed != NULL) {
144 changed = wcsdup(changed + 1);
148 makeShortFilename(filename, buffer_size);
150 if (changed != NULL) {
151 appendWCharSafeW(filename, FILENAME_SEP_CHAR, buffer_size);
152 appendWStringSafeW(filename, changed, buffer_size);
161filename_char_t *_getBinaryPath2(
void) {
162 static filename_char_t binary_filename[MAXPATHLEN] = {0};
163 const size_t buffer_size =
sizeof(binary_filename);
165 if (binary_filename[0] != 0) {
166 return binary_filename;
169#if defined(__APPLE__)
170 uint32_t bufsize = buffer_size;
171 int res = _NSGetExecutablePath(binary_filename, &bufsize);
173 if (unlikely(res != 0)) {
176#elif defined(__OpenBSD__) || defined(_AIX) || defined(_NUITKA_EXPERIMENTAL_FORCE_UNIX_BINARY_NAME)
177#if _NUITKA_DLL_MODE || _NUITKA_MODULE_MODE
178 const char *comm =
"invalid";
179 NUITKA_CANNOT_GET_HERE(
"Cannot query program name on this OS. Please help adding that.");
181 const char *comm = getOriginalArgv0();
184 bool success =
false;
187 copyStringSafe(binary_filename, comm, buffer_size);
190 if (getcwd(binary_filename, buffer_size) == NULL) {
194 appendCharSafe(binary_filename,
'/', buffer_size);
195 appendStringSafe(binary_filename, comm, buffer_size);
197 if (isExecutableFile(binary_filename)) {
200 char *path_environment_value = strdup(getenv(
"PATH"));
202 if (path_environment_value != NULL) {
204 char *path = strtok_r(path_environment_value,
":", &sp);
206 while (path != NULL) {
208 if (getcwd(binary_filename, buffer_size) == NULL) {
212 appendCharSafe(binary_filename,
'/', buffer_size);
214 binary_filename[0] = 0;
216 appendStringSafe(binary_filename, path, buffer_size);
217 appendCharSafe(binary_filename,
'/', buffer_size);
218 appendStringSafe(binary_filename, comm, buffer_size);
220 if (isExecutableFile(binary_filename)) {
225 path = strtok_r(NULL,
":", &sp);
228 free(path_environment_value);
233 if (success ==
true) {
238 normalizePath(binary_filename);
241 fprintf(stderr,
"Error, cannot resolve binary path %s from PATH or current directory.\n", comm);
244#elif defined(__FreeBSD__)
251 mib[2] = KERN_PROC_PATHNAME;
253 size_t cb = buffer_size;
254 int res = sysctl(mib, 4, binary_filename, &cb, NULL, 0);
256 if (unlikely(res != 0)) {
259#elif defined(__wasi__)
260 const char *wasi_filename =
"program.wasm";
261 copyStringSafe(binary_filename, wasi_filename, buffer_size);
267 memset(binary_filename, 0, buffer_size);
268 ssize_t res = readlink(
"/proc/self/exe", binary_filename, buffer_size - 1);
270 if (unlikely(res == -1)) {
274 return binary_filename;
278filename_char_t
const *getBinaryPath(
void) {
280 static filename_char_t binary_filename[MAXPATHLEN] = {0};
282 if (binary_filename[0] != 0) {
283 return binary_filename;
286 DWORD res = GetModuleFileNameW(NULL, binary_filename,
sizeof(binary_filename) /
sizeof(
wchar_t));
287 if (unlikely(res == 0)) {
291 return binary_filename;
293 return _getBinaryPath2();
297bool readFileChunk(FILE_HANDLE file_handle,
void *buffer,
size_t size) {
302 BOOL bool_res = ReadFile(file_handle, buffer, (DWORD)size, &read_size, NULL);
304 return bool_res && (read_size == size);
306 size_t read_size = fread(buffer, 1, size, file_handle);
308 return read_size == size;
312bool writeFileChunk(FILE_HANDLE target_file,
void const *chunk,
size_t chunk_size) {
314 DWORD write_size = 0;
315 return WriteFile(target_file, chunk, (DWORD)chunk_size, &write_size, NULL);
317 size_t written = fwrite(chunk, 1, chunk_size, target_file);
318 return written == chunk_size;
322FILE_HANDLE createFileForWriting(filename_char_t
const *filename) {
324 FILE_HANDLE result = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
326 FILE *result = fopen(filename,
"wb");
332FILE_HANDLE openFileForReading(filename_char_t
const *filename) {
334 FILE_HANDLE result = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
336 FILE *result = fopen(filename,
"rb");
342bool closeFile(FILE_HANDLE target_file) {
344 CloseHandle(target_file);
347 int r = fclose(target_file);
353int64_t getFileSize(FILE_HANDLE file_handle) {
356 DWORD file_size = GetFileSize(file_handle, NULL);
358 if (file_size == INVALID_FILE_SIZE) {
362 int res = fseek(file_handle, 0, SEEK_END);
364 if (unlikely(res != 0)) {
368 long file_size = ftell(file_handle);
370 res = fseek(file_handle, 0, SEEK_SET);
372 if (unlikely(res != 0)) {
377 return (int64_t)file_size;
381#if defined(__APPLE__)
384#if defined(__MSYS__) || defined(__HAIKU__) || defined(__OpenBSD__) || defined(_AIX) || defined(__wasi__)
385static bool sendfile(
int output_file,
int input_file, off_t *bytesCopied,
size_t count) {
391 ssize_t read_bytes = read(input_file, buffer, Py_MIN(
sizeof(buffer), count));
393 if (unlikely(read <= 0)) {
399 ssize_t written_bytes = write(output_file, buffer, read_bytes);
401 if (unlikely(written_bytes != read_bytes)) {
405 *bytesCopied += written_bytes;
410#elif !defined(__FreeBSD__)
411#include <sys/sendfile.h>
417bool isExecutableFile(filename_char_t
const *filename) {
418 int mode = getFileMode(filename);
423 return mode & S_IXUSR;
427int getFileMode(filename_char_t
const *filename) {
429 struct stat fileinfo = {0};
430 if (stat(filename, &fileinfo) == -1) {
434 return fileinfo.st_mode;
441bool copyFile(filename_char_t
const *source, filename_char_t
const *dest,
int mode) {
443 int input_file = open(source, O_RDONLY);
445 if (input_file == -1) {
449 int output_file = creat(dest, mode);
451 if (output_file == -1) {
456#if defined(__APPLE__)
458 bool result = fcopyfile(input_file, output_file, 0, COPYFILE_ALL) == 0;
459#elif defined(__FreeBSD__)
460 struct stat input_fileinfo = {0};
461 fstat(input_file, &input_fileinfo);
462 off_t bytesCopied = 0;
464 bool result = sendfile(output_file, input_file, 0, input_fileinfo.st_size, 0, &bytesCopied, 0);
467 struct stat fileinfo = {0};
468 fstat(input_file, &fileinfo);
470 off_t bytesCopied = 0;
471 bool result = sendfile(output_file, input_file, &bytesCopied, fileinfo.st_size) != -1;
479 return CopyFileW(source, dest, 0) != 0;
483bool deleteFile(filename_char_t
const *filename) {
485 return DeleteFileW(filename) != 0;
487 return unlink(filename) == 0;
491bool renameFile(filename_char_t
const *source, filename_char_t
const *dest) {
494 return _wrename(source, dest) == 0;
496 return rename(source, dest) == 0;
500#include "nuitka/checksum_tools.h"
502extern error_code_t getLastErrorCode(
void) {
504 return GetLastError();
514 char const *erroring_function;
515 unsigned char const *data;
518 HANDLE handle_mapping;
524 result.file_handle = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
525 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
527 if (result.file_handle == INVALID_HANDLE_VALUE) {
529 result.error_code = GetLastError();
530 result.erroring_function =
"CreateFileW";
535 result.file_size = getFileSize(result.file_handle);
537 if (result.file_size == -1) {
539 result.error_code = GetLastError();
540 result.erroring_function =
"GetFileSize";
542 CloseHandle(result.file_handle);
547 result.handle_mapping = CreateFileMappingW(result.file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
549 if (result.handle_mapping == NULL) {
551 result.error_code = GetLastError();
552 result.erroring_function =
"CreateFileMappingW";
554 CloseHandle(result.file_handle);
559 result.data = (
unsigned char const *)MapViewOfFile(result.handle_mapping, FILE_MAP_READ, 0, 0, 0);
561 if (unlikely(result.data == NULL)) {
563 result.error_code = GetLastError();
564 result.erroring_function =
"MapViewOfFile";
566 CloseHandle(result.handle_mapping);
567 CloseHandle(result.file_handle);
572 result.error =
false;
573 result.error_code = 0;
579 assert(!mapped_file->error);
581 UnmapViewOfFile(mapped_file->data);
582 CloseHandle(mapped_file->handle_mapping);
583 CloseHandle(mapped_file->file_handle);
590 char const *erroring_function;
591 unsigned char const *data;
599 result.file_handle = open(filename, O_RDONLY);
601 if (unlikely(result.file_handle == -1)) {
603 result.error_code = errno;
604 result.erroring_function =
"open";
605 result.file_size = -1;
609 result.file_size = lseek(result.file_handle, 0, SEEK_END);
610 if (unlikely(result.file_size == -1)) {
612 result.error_code = errno;
613 result.erroring_function =
"lseek";
615 close(result.file_handle);
619 off_t res = lseek(result.file_handle, 0, SEEK_SET);
621 if (unlikely(res == -1)) {
623 result.error_code = errno;
624 result.erroring_function =
"lseek";
626 close(result.file_handle);
631 result.data = (
unsigned char const *)mmap(NULL, result.file_size, PROT_READ, MAP_PRIVATE, result.file_handle, 0);
633 if (unlikely(result.data == MAP_FAILED)) {
635 result.error_code = errno;
636 result.erroring_function =
"mmap";
638 close(result.file_handle);
643 result.error =
false;
648 assert(!mapped_file->error);
650 munmap((
void *)mapped_file->data, mapped_file->file_size);
651 close(mapped_file->file_handle);
655uint32_t getFileCRC32(filename_char_t
const *filename) {
658 if (mapped_file.error) {
661 uint32_t result = calcCRC32(mapped_file.data, (
long)mapped_file.file_size);
668 unmapFileFromMemory(&mapped_file);
675static DWORD Nuitka_GetFinalPathNameByHandleW(HANDLE hFile, LPWSTR FilePath, DWORD cchFilePath, DWORD dwFlags) {
676 typedef DWORD(WINAPI * pfnGetFinalPathNameByHandleW)(HANDLE hFile, LPWSTR FilePath, DWORD cchFilePath,
679 pfnGetFinalPathNameByHandleW fnGetFinalPathNameByHandleW =
680 (pfnGetFinalPathNameByHandleW)GetProcAddress(GetModuleHandleA(
"Kernel32.dll"),
"GetFinalPathNameByHandleW");
682 if (fnGetFinalPathNameByHandleW != NULL) {
683 return fnGetFinalPathNameByHandleW(hFile, FilePath, cchFilePath, dwFlags);
690static void resolveFileSymbolicLink(
wchar_t *resolved_filename,
wchar_t const *filename, DWORD resolved_filename_size,
691 bool resolve_symlinks) {
695 if (resolve_symlinks) {
697 HANDLE file_handle = CreateFileW(filename, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
698 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
702 copyStringSafeW(resolved_filename, filename, resolved_filename_size);
704 if (unlikely(file_handle == INVALID_HANDLE_VALUE)) {
709 DWORD len = Nuitka_GetFinalPathNameByHandleW(file_handle, resolved_filename, resolved_filename_size,
710 FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
712 CloseHandle(file_handle);
714 if (unlikely(len >= resolved_filename_size)) {
720 if (wcsncmp(resolved_filename, L
"\\\\?\\", 4) == 0) {
721 if (wcscmp(resolved_filename + 4, filename) == 0) {
722 copyStringSafeW(resolved_filename, filename, resolved_filename_size);
723 }
else if (resolved_filename[5] == L
':') {
724 copyStringSafeW(resolved_filename, resolved_filename + 4, resolved_filename_size);
730 if (wcsncmp(resolved_filename, L
"\\\\?\\UNC\\", 8) == 0) {
731 copyStringSafeW(resolved_filename, resolved_filename + 6, resolved_filename_size);
732 resolved_filename[0] = L
'\\';
736 copyStringSafeW(resolved_filename, filename, resolved_filename_size);
742static void resolveFileSymbolicLink(
char *resolved_filename,
char const *filename,
size_t resolved_filename_size,
743 bool resolve_symlinks) {
745 copyStringSafe(resolved_filename, filename, resolved_filename_size);
747 if (resolve_symlinks) {
751 char buffer[MAXPATHLEN];
753 char *result = realpath(filename, buffer);
755 if (unlikely(result == NULL)) {
759 copyStringSafe(resolved_filename, buffer, resolved_filename_size);
761 copyStringSafe(resolved_filename, filename, resolved_filename_size);
768wchar_t const *getBinaryFilenameWideChars(
bool resolve_symlinks) {
769 static wchar_t binary_filename[MAXPATHLEN + 1] = {0};
770 static wchar_t binary_filename_resolved[MAXPATHLEN + 1] = {0};
772 wchar_t *buffer = resolve_symlinks ? binary_filename : binary_filename_resolved;
773 assert(
sizeof(binary_filename) ==
sizeof(binary_filename_resolved));
775 if (buffer[0] == 0) {
776#if _NUITKA_DLL_MODE || _NUITKA_MODULE_MODE
777 if (_pseudo_dll_filename != NULL) {
778 copyStringSafeW(buffer, _pseudo_dll_filename,
sizeof(binary_filename) /
sizeof(
wchar_t));
782 DWORD res = GetModuleFileNameW(NULL, buffer,
sizeof(binary_filename) /
sizeof(
wchar_t));
787 resolveFileSymbolicLink(buffer, buffer,
sizeof(binary_filename) /
sizeof(
wchar_t), resolve_symlinks);
788 makeShortDirFilename(binary_filename,
sizeof(binary_filename) /
sizeof(
wchar_t));
796extern wchar_t const *getBinaryFilenameWideChars(
bool resolve_symlinks);
798char const *getBinaryFilenameHostEncoded(
bool resolve_symlinks) {
799 static char *binary_filename = NULL;
800 static char *binary_filename_resolved = NULL;
802 char *binary_filename_target;
804 if (resolve_symlinks) {
805 binary_filename_target = binary_filename_resolved;
807 binary_filename_target = binary_filename;
810 if (binary_filename_target != NULL) {
811 return binary_filename_target;
813 wchar_t const *w = getBinaryFilenameWideChars(resolve_symlinks);
815 DWORD bufsize = WideCharToMultiByte(CP_ACP, 0, w, -1, NULL, 0, NULL, NULL);
816 assert(bufsize != 0);
818 binary_filename_target = (
char *)malloc(bufsize + 1);
819 assert(binary_filename_target);
821 DWORD res2 = WideCharToMultiByte(CP_ACP, 0, w, -1, binary_filename_target, bufsize, NULL, NULL);
824 if (unlikely(res2 > bufsize)) {
828 return (
char const *)binary_filename_target;
832char const *getBinaryFilenameHostEncoded(
bool resolve_symlinks) {
833 const int buffer_size = MAXPATHLEN + 1;
835 static char binary_filename[MAXPATHLEN + 1] = {0};
836 static char binary_filename_resolved[MAXPATHLEN + 1] = {0};
838 char *binary_filename_target;
840 if (resolve_symlinks) {
841 binary_filename_target = binary_filename_resolved;
843 binary_filename_target = binary_filename;
846 if (*binary_filename_target != 0) {
847 return binary_filename_target;
850 copyStringSafe(binary_filename_target, _getBinaryPath2(), buffer_size);
851 resolveFileSymbolicLink(binary_filename_target, binary_filename_target, buffer_size, resolve_symlinks);
853 return binary_filename_target;
857static void generateXorShift32RandomBytes(
unsigned int state,
unsigned char *buffer,
size_t length) {
865 for (
size_t i = 0; i < length; i++) {
866 state ^= state << 13;
867 state ^= state >> 17;
871 buffer[i] = (
unsigned char)state;
884#ifndef CSIDL_LOCAL_APPDATA
885#define CSIDL_LOCAL_APPDATA 28
888#define CSIDL_PROFILE 40
893static bool appendStringCSIDLPathW(
wchar_t *target,
int csidl_id,
size_t buffer_size) {
894 wchar_t path_buffer[MAX_PATH];
895 int res = SHGetFolderPathW(NULL, csidl_id, NULL, 0, path_buffer);
900 appendWStringSafeW(target, path_buffer, buffer_size);
905static void getSecureRandomBytes(
unsigned char *buffer,
size_t length) {
907 QueryPerformanceCounter(&li);
909 unsigned int folded_time = (
unsigned int)(li.QuadPart ^ (li.QuadPart >> 32));
912 unsigned int folded_ptr = (
unsigned int)(((
size_t)&li) ^ (((
size_t)&li) >> 32));
914 unsigned int folded_ptr = (
unsigned int)((
size_t)&li);
917 unsigned int seed = folded_time ^ folded_ptr ^ GetCurrentProcessId();
919 generateXorShift32RandomBytes(seed, buffer, length);
922static void formatRandomBase64URLW(
unsigned char const *rand_bytes,
wchar_t *random_buffer) {
923 wchar_t const *alphabet = L
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
925 random_buffer[0] = alphabet[(rand_bytes[0] >> 2)];
926 random_buffer[1] = alphabet[(((rand_bytes[0] & 0x3) << 4) | (rand_bytes[1] >> 4))];
927 random_buffer[2] = alphabet[(((rand_bytes[1] & 0xF) << 2) | (rand_bytes[2] >> 6))];
928 random_buffer[3] = alphabet[(rand_bytes[2] & 0x3F)];
930 random_buffer[4] = alphabet[(rand_bytes[3] >> 2)];
931 random_buffer[5] = alphabet[(((rand_bytes[3] & 0x3) << 4) | (rand_bytes[4] >> 4))];
932 random_buffer[6] = alphabet[(((rand_bytes[4] & 0xF) << 2) | (rand_bytes[5] >> 6))];
933 random_buffer[7] = alphabet[(rand_bytes[5] & 0x3F)];
935 random_buffer[8] = alphabet[(rand_bytes[6] >> 2)];
936 random_buffer[9] = alphabet[(((rand_bytes[6] & 0x3) << 4) | (rand_bytes[7] >> 4))];
937 random_buffer[10] = alphabet[((rand_bytes[7] & 0xF) << 2)];
938 random_buffer[11] = L
'\0';
941bool expandTemplatePathW(
wchar_t *target,
wchar_t const *source,
size_t buffer_size) {
944 wchar_t var_name[1024];
947 bool var_started =
false;
949 while (*source != 0) {
950 if (*source == L
'{') {
951 assert(var_started ==
false);
960 }
else if (*source == L
'}') {
961 assert(var_started ==
true);
966 bool is_path =
false;
968 if (wcsicmp(var_name, L
"TEMP") == 0) {
969 GetTempPathW((DWORD)buffer_size, target);
971 }
else if (wcsicmp(var_name, L
"PROGRAM") == 0) {
972#if _NUITKA_ONEFILE_TEMP_BOOL
973 appendWStringSafeW(target, __wargv[0], buffer_size);
975 if (!GetModuleFileNameW(NULL, target, (DWORD)buffer_size)) {
979 }
else if (wcsicmp(var_name, L
"PROGRAM_BASE") == 0) {
980 if (expandTemplatePathW(target, L
"{PROGRAM}", buffer_size - wcslen(target)) ==
false) {
984 size_t length = wcslen(target);
986 if ((length >= 4) && (wcsicmp(target + length - 4, L
".exe") == 0)) {
987 target[length - 4] = 0;
989 }
else if (wcsicmp(var_name, L
"PROGRAM_DIR") == 0) {
990 if (expandTemplatePathW(target, L
"{PROGRAM}", buffer_size - wcslen(target)) ==
false) {
994 stripFilenameW(target);
995 }
else if (wcsicmp(var_name, L
"PID") == 0) {
997 environment_char_t
const *environment_value = NULL;
999#if _NUITKA_ONEFILE_MODE
1000 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_PARENT");
1002 if (environment_value != NULL) {
1003 checkWStringNumber(environment_value);
1005 appendWStringSafeW(target, getEnvironmentVariable(
"NUITKA_ONEFILE_PARENT"), buffer_size);
1007 char pid_buffer[128];
1008 snprintf(pid_buffer,
sizeof(pid_buffer),
"%ld", GetCurrentProcessId());
1009 appendStringSafeW(target, pid_buffer, buffer_size);
1011 }
else if (wcsicmp(var_name, L
"HOME") == 0) {
1012 if (appendStringCSIDLPathW(target, CSIDL_PROFILE, buffer_size) ==
false) {
1016 }
else if (wcsicmp(var_name, L
"CACHE_DIR") == 0) {
1017 if (appendStringCSIDLPathW(target, CSIDL_LOCAL_APPDATA, buffer_size) ==
false) {
1021#ifdef NUITKA_COMPANY_NAME
1022 }
else if (wcsicmp(var_name, L
"COMPANY") == 0) {
1023 appendWStringSafeW(target, L
"" NUITKA_COMPANY_NAME, buffer_size);
1025#ifdef NUITKA_PRODUCT_NAME
1026 }
else if (wcsicmp(var_name, L
"PRODUCT") == 0) {
1027 appendWStringSafeW(target, L
"" NUITKA_PRODUCT_NAME, buffer_size);
1029#ifdef NUITKA_VERSION_COMBINED
1030 }
else if (wcsicmp(var_name, L
"VERSION") == 0) {
1031 appendWStringSafeW(target, L
"" NUITKA_VERSION_COMBINED, buffer_size);
1033#ifdef NUITKA_FILE_VERSION
1034 }
else if (wcsicmp(var_name, L
"FILE_VERSION") == 0) {
1035 appendWStringSafeW(target, L
"" NUITKA_FILE_VERSION, buffer_size);
1037#ifdef NUITKA_PRODUCT_VERSION
1038 }
else if (wcsicmp(var_name, L
"PRODUCT_VERSION") == 0) {
1039 appendWStringSafeW(target, L
"" NUITKA_PRODUCT_VERSION, buffer_size);
1041 }
else if (wcsicmp(var_name, L
"RANDOM") == 0) {
1042 environment_char_t
const *environment_value = NULL;
1044#if _NUITKA_ONEFILE_MODE
1045 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_RANDOM");
1048 if (environment_value != NULL) {
1049 appendWStringSafeW(target, getEnvironmentVariable(
"NUITKA_ONEFILE_RANDOM"), buffer_size);
1051 unsigned char rand_bytes[8];
1052 getSecureRandomBytes(rand_bytes,
sizeof(rand_bytes));
1054 wchar_t random_buffer[12];
1055 formatRandomBase64URLW(rand_bytes, random_buffer);
1057#if _NUITKA_ONEFILE_MODE
1058 setEnvironmentVariable(
"NUITKA_ONEFILE_RANDOM", random_buffer);
1061 appendWStringSafeW(target, random_buffer, buffer_size);
1063 }
else if (wcsicmp(var_name, L
"TIME_US") == 0) {
1064 environment_char_t
const *environment_value = NULL;
1066#if _NUITKA_ONEFILE_MODE
1067 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_TIME_US");
1070 if (environment_value != NULL) {
1071 appendWStringSafeW(target, getEnvironmentVariable(
"NUITKA_ONEFILE_TIME_US"), buffer_size);
1073 wchar_t time_buffer[128];
1076 assert(
sizeof(time) ==
sizeof(FILETIME));
1077 GetSystemTimeAsFileTime((LPFILETIME)&time);
1079 long usec = (long)((time / 10) % 1000000);
1080 swprintf(time_buffer,
sizeof(time_buffer), L
"%06ld", usec);
1082#if _NUITKA_ONEFILE_MODE
1083 setEnvironmentVariable(
"NUITKA_ONEFILE_TIME_US", time_buffer);
1086 appendWStringSafeW(target, time_buffer, buffer_size);
1088 }
else if (wcsicmp(var_name, L
"TIME") == 0) {
1089 environment_char_t
const *environment_value = NULL;
1091#if _NUITKA_ONEFILE_MODE
1092 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_START");
1095 if (environment_value != NULL) {
1096 appendWStringSafeW(target, getEnvironmentVariable(
"NUITKA_ONEFILE_START"), buffer_size);
1098 wchar_t time_buffer[1024];
1102 assert(
sizeof(time) ==
sizeof(FILETIME));
1103 GetSystemTimeAsFileTime((LPFILETIME)&time);
1105 swprintf(time_buffer,
sizeof(time_buffer), L
"%lld", time);
1107#if _NUITKA_ONEFILE_MODE
1108 setEnvironmentVariable(
"NUITKA_ONEFILE_START", time_buffer);
1110 appendWStringSafeW(target, time_buffer, buffer_size);
1124 while (*(target - 1) == FILENAME_SEP_CHAR) {
1142 if (buffer_size < 1) {
1146 *target++ = *source++;
1153 assert(var_started ==
false);
1159#if defined(_MSC_VER) && (defined(__i386__) || defined(__x86_64__))
1163static uint64_t getCpuCycleCounter(
void) {
1164#if defined(__i386__) || defined(__x86_64__)
1165#if defined(_MSC_VER)
1168 unsigned int low_value;
1169 unsigned int high_value;
1171 __asm__
volatile(
"rdtsc" :
"=a"(low_value),
"=d"(high_value));
1173 return (((uint64_t)high_value) << 32) | low_value;
1175#elif defined(__aarch64__)
1177 __asm__
volatile(
"mrs %0, cntvct_el0" :
"=r"(val));
1184static void getSecureRandomBytes(
unsigned char *buffer,
size_t length) {
1185 int fd = open(
"/dev/urandom", O_RDONLY);
1187 ssize_t res = read(fd, buffer, length);
1189 if (res == (ssize_t)length) {
1194 uint64_t cycles = getCpuCycleCounter();
1196 unsigned int folded_time = (
unsigned int)(cycles ^ (cycles >> 32));
1199 unsigned int folded_ptr = (
unsigned int)(((
size_t)&cycles) ^ (((
size_t)&cycles) >> 32));
1201 unsigned int folded_ptr = (
unsigned int)((
size_t)&cycles);
1204 unsigned int seed = folded_time ^ folded_ptr;
1206 generateXorShift32RandomBytes(seed, buffer, length);
1209static void formatRandomBase64URL(
unsigned char const *rand_bytes,
char *random_buffer) {
1210 char const *alphabet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
1212 random_buffer[0] = alphabet[(rand_bytes[0] >> 2)];
1213 random_buffer[1] = alphabet[(((rand_bytes[0] & 0x3) << 4) | (rand_bytes[1] >> 4))];
1214 random_buffer[2] = alphabet[(((rand_bytes[1] & 0xF) << 2) | (rand_bytes[2] >> 6))];
1215 random_buffer[3] = alphabet[(rand_bytes[2] & 0x3F)];
1217 random_buffer[4] = alphabet[(rand_bytes[3] >> 2)];
1218 random_buffer[5] = alphabet[(((rand_bytes[3] & 0x3) << 4) | (rand_bytes[4] >> 4))];
1219 random_buffer[6] = alphabet[(((rand_bytes[4] & 0xF) << 2) | (rand_bytes[5] >> 6))];
1220 random_buffer[7] = alphabet[(rand_bytes[5] & 0x3F)];
1222 random_buffer[8] = alphabet[(rand_bytes[6] >> 2)];
1223 random_buffer[9] = alphabet[(((rand_bytes[6] & 0x3) << 4) | (rand_bytes[7] >> 4))];
1224 random_buffer[10] = alphabet[((rand_bytes[7] & 0xF) << 2)];
1225 random_buffer[11] =
'\0';
1228bool expandTemplatePath(
char *target,
char const *source,
size_t buffer_size) {
1231 char var_name[1024];
1234 NUITKA_MAY_BE_UNUSED
bool var_started =
false;
1236 while (*source != 0) {
1237 if (*source ==
'{') {
1238 assert(var_started ==
false);
1247 }
else if (*source ==
'}') {
1248 assert(var_started ==
true);
1249 var_started =
false;
1252 bool is_path =
false;
1254 if (strcasecmp(var_name,
"TEMP") == 0) {
1255 char const *tmp_dir = getenv(
"TMPDIR");
1256 if (tmp_dir == NULL) {
1260 appendStringSafe(target, tmp_dir, buffer_size);
1262 }
else if (strcasecmp(var_name,
"PROGRAM") == 0) {
1263 char const *exe_name = getBinaryFilenameHostEncoded(
false);
1265 appendStringSafe(target, exe_name, buffer_size);
1266 }
else if (strcasecmp(var_name,
"PROGRAM_BASE") == 0) {
1267 if (expandTemplatePath(target,
"{PROGRAM}", buffer_size - strlen(target)) ==
false) {
1271 size_t length = strlen(target);
1273 if ((length >= 4) && (strcasecmp(target + length - 4,
".bin") == 0)) {
1274 target[length - 4] = 0;
1276 }
else if (strcasecmp(var_name,
"PROGRAM_DIR") == 0) {
1277 if (expandTemplatePath(target,
"{PROGRAM}", buffer_size - strlen(target)) ==
false) {
1281 size_t length = strlen(target);
1291 if (target[length] ==
'/') {
1299 }
else if (strcasecmp(var_name,
"PID") == 0) {
1301 environment_char_t
const *environment_value = NULL;
1303#if _NUITKA_ONEFILE_MODE
1304 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_PARENT");
1306 if (environment_value != NULL) {
1307 checkStringNumber(environment_value);
1309 appendStringSafe(target, getEnvironmentVariable(
"NUITKA_ONEFILE_PARENT"), buffer_size);
1311 char pid_buffer[128];
1313 snprintf(pid_buffer,
sizeof(pid_buffer),
"%d", getpid());
1315 appendStringSafe(target, pid_buffer, buffer_size);
1317 }
else if (strcasecmp(var_name,
"HOME") == 0) {
1318 char const *home_path = getenv(
"HOME");
1319 if (home_path == NULL) {
1323 struct passwd *pw_data = getpwuid(getuid());
1325 if (unlikely(pw_data == NULL)) {
1329 home_path = pw_data->pw_dir;
1333 appendStringSafe(target, home_path, buffer_size);
1335 }
else if (strcasecmp(var_name,
"CACHE_DIR") == 0) {
1336 char const *xdg_cache_home = getenv(
"XDG_CACHE_HOME");
1338 if (xdg_cache_home != NULL && xdg_cache_home[0] ==
'/') {
1339 appendStringSafe(target, xdg_cache_home, buffer_size);
1341 if (expandTemplatePath(target,
"{HOME}/.cache", buffer_size - strlen(target)) ==
false) {
1346#ifdef NUITKA_COMPANY_NAME
1347 }
else if (strcasecmp(var_name,
"COMPANY") == 0) {
1348 appendStringSafe(target, NUITKA_COMPANY_NAME, buffer_size);
1350#ifdef NUITKA_PRODUCT_NAME
1351 }
else if (strcasecmp(var_name,
"PRODUCT") == 0) {
1352 appendStringSafe(target, NUITKA_PRODUCT_NAME, buffer_size);
1354#ifdef NUITKA_VERSION_COMBINED
1355 }
else if (strcasecmp(var_name,
"VERSION") == 0) {
1356 appendStringSafe(target, NUITKA_VERSION_COMBINED, buffer_size);
1358#ifdef NUITKA_FILE_VERSION
1359 }
else if (strcasecmp(var_name,
"FILE_VERSION") == 0) {
1360 appendStringSafe(target, NUITKA_FILE_VERSION, buffer_size);
1362#ifdef NUITKA_PRODUCT_VERSION
1363 }
else if (strcasecmp(var_name,
"PRODUCT_VERSION") == 0) {
1364 appendStringSafe(target, NUITKA_PRODUCT_VERSION, buffer_size);
1366 }
else if (strcasecmp(var_name,
"RANDOM") == 0) {
1367 environment_char_t
const *environment_value = NULL;
1369#if _NUITKA_ONEFILE_MODE
1370 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_RANDOM");
1373 if (environment_value != NULL) {
1374 appendStringSafe(target, getEnvironmentVariable(
"NUITKA_ONEFILE_RANDOM"), buffer_size);
1376 unsigned char rand_bytes[8];
1377 getSecureRandomBytes(rand_bytes,
sizeof(rand_bytes));
1379 char random_buffer[12];
1380 formatRandomBase64URL(rand_bytes, random_buffer);
1382#if _NUITKA_ONEFILE_MODE
1383 setEnvironmentVariable(
"NUITKA_ONEFILE_RANDOM", random_buffer);
1386 appendStringSafe(target, random_buffer, buffer_size);
1388 }
else if (strcasecmp(var_name,
"TIME_US") == 0) {
1389 environment_char_t
const *environment_value = NULL;
1391#if _NUITKA_ONEFILE_MODE
1392 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_TIME_US");
1395 if (environment_value != NULL) {
1396 appendStringSafe(target, getEnvironmentVariable(
"NUITKA_ONEFILE_TIME_US"), buffer_size);
1398 char time_buffer[128];
1400 struct timeval current_time;
1401 gettimeofday(¤t_time, NULL);
1403 snprintf(time_buffer,
sizeof(time_buffer),
"%06ld", (
long)current_time.tv_usec);
1405#if _NUITKA_ONEFILE_MODE
1406 setEnvironmentVariable(
"NUITKA_ONEFILE_TIME_US", time_buffer);
1409 appendStringSafe(target, time_buffer, buffer_size);
1411 }
else if (strcasecmp(var_name,
"TIME") == 0) {
1412 environment_char_t
const *environment_value = NULL;
1414#if _NUITKA_ONEFILE_MODE
1415 environment_value = getEnvironmentVariable(
"NUITKA_ONEFILE_START");
1418 if (environment_value != NULL) {
1419 appendStringSafe(target, getEnvironmentVariable(
"NUITKA_ONEFILE_START"), buffer_size);
1421 char time_buffer[1024];
1423 struct timeval current_time;
1424 gettimeofday(¤t_time, NULL);
1425 snprintf(time_buffer,
sizeof(time_buffer),
"%ld_%ld", current_time.tv_sec,
1426 (
long)current_time.tv_usec);
1428#if _NUITKA_ONEFILE_MODE
1429 setEnvironmentVariable(
"NUITKA_ONEFILE_START", time_buffer);
1432 appendStringSafe(target, time_buffer, buffer_size);
1444 while (*(target - 1) == FILENAME_SEP_CHAR) {
1462 if (buffer_size < 1) {
1466 *target++ = *source++;
1473 assert(var_started ==
false);
1479#if _NUITKA_DLL_MODE || _NUITKA_MODULE_MODE
1483static HMODULE getDllModuleHandle(
void) {
1484 static HMODULE hm = NULL;
1488 GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
1489 (LPCSTR)&getDllModuleHandle, &hm);
1499#include "AixDllAddr.c"
1502static filename_char_t
const *getDllFilename(
void) {
1503 if (_pseudo_dll_filename != NULL) {
1504 return _pseudo_dll_filename;
1508 static WCHAR dll_filename[MAXPATHLEN + 1] = {0};
1510 if (dll_filename[0] == 0) {
1511 int res = GetModuleFileNameW(getDllModuleHandle(), dll_filename, MAXPATHLEN);
1514 makeShortDirFilename(dll_filename,
sizeof(dll_filename) /
sizeof(
wchar_t));
1517 return dll_filename;
1522 NUITKA_MAY_BE_UNUSED
int res = dladdr((
void *)getDllDirectory, &where);
1526 return where.dli_fname;
1530filename_char_t
const *getDllDirectory(
void) {
1532 static WCHAR path[MAXPATHLEN + 1] = {0};
1534 copyStringSafeFilename(path, getDllFilename(), MAXPATHLEN);
1535 stripFilenameW(path);
1541 static char const *result = NULL;
1543 if (result == NULL) {
1547 NUITKA_MAY_BE_UNUSED
int res = dladdr((
void *)getDllDirectory, &where);
1551 result = dirname((
char *)strdup(where.dli_fname));
Definition HelpersFilesystemPaths.c:587