// TODO rename fuction and revisit int pyi_get_temp_path(char *buffer) { int i; char *ret; char prefix[16]; wchar_t wchar_buffer[PATH_MAX]; /* * Get path to Windows temporary directory. */ GetTempPathW(PATH_MAX, wchar_buffer); pyi_win32_utils_to_utf8(buffer, wchar_buffer, PATH_MAX); sprintf(prefix, "_MEI%d", getpid()); /* * Windows does not have a race-free function to create a temporary * directory. Thus, we rely on _tempnam, and simply try several times * to avoid stupid race conditions. */ for (i=0;i<5;i++) { // TODO use race-free fuction - if any exists? ret = _tempnam(buffer, prefix); if (mkdir(ret) == 0) { strcpy(buffer, ret); free(ret); return 1; } free(ret); } return 0; }
char * GetWinErrorString(DWORD error_code) { wchar_t local_buffer[ERROR_STRING_MAX]; DWORD result; if (error_code == 0) { error_code = GetLastError(); } /* Note: Giving 0 to dwLanguageID means MAKELANGID(LANG_NEUTRAL, * SUBLANG_NEUTRAL), but we should use SUBLANG_DEFAULT instead of * SUBLANG_NEUTRAL. Please see the note written in * "Language Identifier Constants and Strings" on MSDN. * https://docs.microsoft.com/en-us/windows/desktop/intl/language-identifier-constants-and-strings */ result = FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, // dwFlags NULL, // lpSource error_code, // dwMessageID MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // dwLanguageID local_buffer, // lpBuffer ERROR_STRING_MAX, // nSize NULL // Arguments ); if (!result) { FATAL_WINERROR("FormatMessageW", "No error messages generated.\n"); return "PyInstaller: FormatMessageW failed."; } if (!pyi_win32_utils_to_utf8(errorString, local_buffer, ERROR_STRING_MAX)) { return "PyInstaller: pyi_win32_utils_to_utf8 failed."; } return errorString; }
/* Return string copy of environment variable. */ char *pyi_getenv(const char *variable) { char *env = NULL; #ifdef _WIN32 wchar_t * wenv = NULL; wchar_t * wvar = NULL; wchar_t buf1[PATH_MAX], buf2[PATH_MAX]; DWORD rc; wvar = pyi_win32_utils_from_utf8(NULL, variable, 0); rc = GetEnvironmentVariableW(wvar, buf1, sizeof(buf1)); if(rc > 0) { wenv = buf1; /* Expand environment variables like %VAR% in value. */ rc = ExpandEnvironmentStringsW(wenv, buf2, sizeof(buf2)); if(rc > 0) { wenv = buf1; } } if(wenv) { env = pyi_win32_utils_to_utf8(NULL, wenv, 0); } #else /* Standard POSIX function. */ env = getenv(variable); #endif /* If the Python program we are about to run invokes another PyInstaller * one-file program as subprocess, this subprocess must not be fooled into * thinking that it is already unpacked. Therefore, PyInstaller deletes * the _MEIPASS2 variable from the environment in pyi_main(). * * However, on some platforms (e.g. AIX) the Python function 'os.unsetenv()' * does not always exist. In these cases we cannot delete the _MEIPASS2 * environment variable from Python but only set it to the empty string. * The code below takes into account that a variable may exist while its * value is only the empty string. * * Return copy of string to avoid modification of the process environment. */ return (env && env[0]) ? strdup(env) : NULL; }
/* * Return full path to the current executable. * Executable is the .exe created by pyinstaller: path/myappname.exe * Because the calling process can set argv[0] to whatever it wants, * we use a few alternate methods to get the executable path. * * execfile - buffer where to put path to executable. * appname - usually the item argv[0]. */ int pyi_path_executable(char *execfile, const char *appname) { char buffer[PATH_MAX]; size_t result = -1; #ifdef _WIN32 wchar_t modulename_w[PATH_MAX]; /* GetModuleFileNameW returns an absolute, fully qualified path */ if (!GetModuleFileNameW(NULL, modulename_w, PATH_MAX)) { FATALERROR("Failed to get executable path. \nGetModuleFileNameW: %s", GetWinErrorString()); return -1; } if (!pyi_win32_utils_to_utf8(execfile, modulename_w, PATH_MAX)) { FATALERROR("Failed to convert executable path to UTF-8.", GetWinErrorString()); return -1; } #elif __APPLE__ uint32_t length = sizeof(buffer); /* Mac OS X has special function to obtain path to executable. * This may return a symlink. */ if (_NSGetExecutablePath(buffer, &length) != 0) { FATALERROR("System error - unable to load!"); return -1; } if (pyi_path_fullpath(execfile, PATH_MAX, buffer) == false) { VS("LOADER: Cannot get fullpath for %s\n", execfile); return -1; } #else /* ifdef _WIN32 */ result = -1; /* On Linux, FreeBSD, and Solaris, we try these /proc paths first */ #if defined(__linux__) result = readlink("/proc/self/exe", execfile, PATH_MAX); /* Linux */ #elif defined(__FreeBSD__) result = readlink("/proc/curproc/file", execfile, PATH_MAX); /* FreeBSD */ #elif defined(__sun) result = readlink("/proc/self/path/a.out", execfile, PATH_MAX); /* Solaris */ #endif if (-1 != result) { /* execfile is not yet zero-terminated. result is the byte count. */ *(execfile + result) = '\0'; } else { /* No /proc path found or provided */ if (appname[0] == PYI_SEP || strchr(appname, PYI_SEP)) { /* Absolute or relative path. * Convert to absolute and resolve symlinks. */ if (pyi_path_fullpath(execfile, PATH_MAX, appname) == false) { VS("LOADER: Cannot get fullpath for %s\n", execfile); return -1; } } else { /* Not absolute or relative path, just program name. Search $PATH */ result = pyi_search_path(buffer, appname); if (-1 == result) { /* Searching $PATH failed, user is crazy. */ VS("LOADER: Searching $PATH failed for %s", appname); strcpy(buffer, appname); } if (pyi_path_fullpath(execfile, PATH_MAX, buffer) == false) { VS("LOADER: Cannot get fullpath for %s\n", execfile); return -1; } } } #endif /* ifdef _WIN32 */ VS("LOADER: executable is %s\n", execfile); return 0; }