mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-11-03 19:17:02 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			263 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
//-----------------------------------------------------------------------------
 | 
						|
// Common.c
 | 
						|
//   Routines which are common to running frozen executables.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
 | 
						|
#include <compile.h>
 | 
						|
#include <eval.h>
 | 
						|
#include <osdefs.h>
 | 
						|
 | 
						|
// global variables (used for simplicity)
 | 
						|
static PyObject *g_FileName = NULL;
 | 
						|
static PyObject *g_DirName = NULL;
 | 
						|
static PyObject *g_ExclusiveZipFileName = NULL;
 | 
						|
static PyObject *g_SharedZipFileName = NULL;
 | 
						|
static PyObject *g_InitScriptZipFileName = NULL;
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// GetDirName()
 | 
						|
//   Return the directory name of the given path.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
static int GetDirName(
 | 
						|
    const char *path,                   // path to calculate dir name for
 | 
						|
    PyObject **dirName)                 // directory name (OUT)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = strlen(path); i > 0 && path[i] != SEP; --i);
 | 
						|
    *dirName = PyString_FromStringAndSize(path, i);
 | 
						|
    if (!*dirName)
 | 
						|
        return FatalError("cannot create string for directory name");
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// SetExecutableName()
 | 
						|
//   Set the script to execute and calculate the directory in which the
 | 
						|
// executable is found as well as the exclusive (only for this executable) and
 | 
						|
// shared zip file names.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
static int SetExecutableName(
 | 
						|
    const char *fileName)               // script to execute
 | 
						|
{
 | 
						|
    char temp[MAXPATHLEN + 12], *ptr;
 | 
						|
#ifndef WIN32
 | 
						|
    char linkData[MAXPATHLEN + 1];
 | 
						|
    struct stat statData;
 | 
						|
    size_t linkSize, i;
 | 
						|
    PyObject *dirName;
 | 
						|
#endif
 | 
						|
 | 
						|
    // store file name
 | 
						|
    g_FileName = PyString_FromString(fileName);
 | 
						|
    if (!g_FileName)
 | 
						|
        return FatalError("cannot create string for file name");
 | 
						|
 | 
						|
#ifndef WIN32
 | 
						|
    for (i = 0; i < 25; i++) {
 | 
						|
        if (lstat(fileName, &statData) < 0) {
 | 
						|
            PyErr_SetFromErrnoWithFilename(PyExc_OSError, (char*) fileName);
 | 
						|
            return FatalError("unable to stat file");
 | 
						|
        }
 | 
						|
        if (!S_ISLNK(statData.st_mode))
 | 
						|
            break;
 | 
						|
        linkSize = readlink(fileName, linkData, sizeof(linkData));
 | 
						|
        if (linkSize < 0) {
 | 
						|
            PyErr_SetFromErrnoWithFilename(PyExc_OSError, (char*) fileName);
 | 
						|
            return FatalError("unable to stat file");
 | 
						|
        }
 | 
						|
        if (linkData[0] == '/') {
 | 
						|
            Py_DECREF(g_FileName);
 | 
						|
            g_FileName = PyString_FromStringAndSize(linkData, linkSize);
 | 
						|
        } else {
 | 
						|
            if (GetDirName(PyString_AS_STRING(g_FileName), &dirName) < 0)
 | 
						|
                return -1;
 | 
						|
            if (PyString_GET_SIZE(dirName) + linkSize + 1 > MAXPATHLEN) {
 | 
						|
                Py_DECREF(dirName);
 | 
						|
                return FatalError("cannot dereference link, path too large");
 | 
						|
            }
 | 
						|
            strcpy(temp, PyString_AS_STRING(dirName));
 | 
						|
            strcat(temp, "/");
 | 
						|
            strcat(temp, linkData);
 | 
						|
            Py_DECREF(g_FileName);
 | 
						|
            g_FileName = PyString_FromString(temp);
 | 
						|
        }
 | 
						|
        if (!g_FileName)
 | 
						|
            return FatalError("cannot create string for linked file name");
 | 
						|
        fileName = PyString_AS_STRING(g_FileName);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    // calculate and store directory name
 | 
						|
    if (GetDirName(fileName, &g_DirName) < 0)
 | 
						|
        return -1;
 | 
						|
 | 
						|
    // calculate and store exclusive zip file name
 | 
						|
    strcpy(temp, fileName);
 | 
						|
    ptr = temp + strlen(temp) - 1;
 | 
						|
    while (ptr > temp && *ptr != SEP && *ptr != '.')
 | 
						|
        ptr--;
 | 
						|
    if (*ptr == '.')
 | 
						|
        *ptr = '\0';
 | 
						|
    strcat(temp, ".zip");
 | 
						|
    g_ExclusiveZipFileName = PyString_FromString(temp);
 | 
						|
    if (!g_ExclusiveZipFileName)
 | 
						|
        return FatalError("cannot create string for exclusive zip file name");
 | 
						|
 | 
						|
    // calculate and store shared zip file name
 | 
						|
    strcpy(temp, PyString_AS_STRING(g_DirName));
 | 
						|
    ptr = temp + strlen(temp);
 | 
						|
    *ptr++ = SEP;
 | 
						|
    strcpy(ptr, "library.zip");
 | 
						|
    g_SharedZipFileName = PyString_FromString(temp);
 | 
						|
    if (!g_SharedZipFileName)
 | 
						|
        return FatalError("cannot create string for shared zip file name");
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// SetPathToSearch()
 | 
						|
//   Set the path to search. This includes the file (for those situations where
 | 
						|
// a zip file is attached to the executable itself), the directory where the
 | 
						|
// executable is found (to search for extensions), the exclusive zip file
 | 
						|
// name and the shared zip file name.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
static int SetPathToSearch(void)
 | 
						|
{
 | 
						|
    PyObject *pathList;
 | 
						|
 | 
						|
    pathList = PySys_GetObject("path");
 | 
						|
    if (!pathList)
 | 
						|
        return FatalError("cannot acquire sys.path");
 | 
						|
    if (PyList_Insert(pathList, 0, g_FileName) < 0)
 | 
						|
        return FatalError("cannot insert file name into sys.path");
 | 
						|
    if (PyList_Insert(pathList, 1, g_DirName) < 0)
 | 
						|
        return FatalError("cannot insert directory name into sys.path");
 | 
						|
    if (PyList_Insert(pathList, 2, g_ExclusiveZipFileName) < 0)
 | 
						|
        return FatalError("cannot insert exclusive zip name into sys.path");
 | 
						|
    if (PyList_Insert(pathList, 3, g_SharedZipFileName) < 0)
 | 
						|
        return FatalError("cannot insert shared zip name into sys.path");
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// GetImporterHelper()
 | 
						|
//   Helper which is used to locate the importer for the initscript.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
static PyObject *GetImporterHelper(
 | 
						|
    PyObject *module,                   // zipimport module
 | 
						|
    PyObject *fileName)                 // name of file to search
 | 
						|
{
 | 
						|
    PyObject *importer;
 | 
						|
 | 
						|
    importer = PyObject_CallMethod(module, "zipimporter", "O", fileName);
 | 
						|
    if (importer)
 | 
						|
        g_InitScriptZipFileName = fileName;
 | 
						|
    else
 | 
						|
        PyErr_Clear();
 | 
						|
    return importer;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// GetImporter()
 | 
						|
//   Return the importer which will be used for importing the initialization
 | 
						|
// script. The executable itself is searched first, followed by the exclusive
 | 
						|
// zip file and finally by the shared zip file.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
static int GetImporter(
 | 
						|
    PyObject **importer)                // importer (OUT)
 | 
						|
{
 | 
						|
    PyObject *module;
 | 
						|
 | 
						|
    module = PyImport_ImportModule("zipimport");
 | 
						|
    if (!module)
 | 
						|
        return FatalError("cannot import zipimport module");
 | 
						|
    *importer = GetImporterHelper(module, g_FileName);
 | 
						|
    if (!*importer) {
 | 
						|
        *importer = GetImporterHelper(module, g_ExclusiveZipFileName);
 | 
						|
        if (!*importer)
 | 
						|
            *importer = GetImporterHelper(module, g_SharedZipFileName);
 | 
						|
    }
 | 
						|
    Py_DECREF(module);
 | 
						|
    if (!*importer)
 | 
						|
        return FatalError("cannot get zipimporter instance");
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// PopulateInitScriptDict()
 | 
						|
//   Return the dictionary used by the initialization script.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
static int PopulateInitScriptDict(
 | 
						|
    PyObject *dict)                     // dictionary to populate
 | 
						|
{
 | 
						|
    if (!dict)
 | 
						|
        return FatalError("unable to create temporary dictionary");
 | 
						|
    if (PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0)
 | 
						|
        return FatalError("unable to set __builtins__");
 | 
						|
    if (PyDict_SetItemString(dict, "FILE_NAME", g_FileName) < 0)
 | 
						|
        return FatalError("unable to set FILE_NAME");
 | 
						|
    if (PyDict_SetItemString(dict, "DIR_NAME", g_DirName) < 0)
 | 
						|
        return FatalError("unable to set DIR_NAME");
 | 
						|
    if (PyDict_SetItemString(dict, "EXCLUSIVE_ZIP_FILE_NAME",
 | 
						|
            g_ExclusiveZipFileName) < 0)
 | 
						|
        return FatalError("unable to set EXCLUSIVE_ZIP_FILE_NAME");
 | 
						|
    if (PyDict_SetItemString(dict, "SHARED_ZIP_FILE_NAME",
 | 
						|
            g_SharedZipFileName) < 0)
 | 
						|
        return FatalError("unable to set SHARED_ZIP_FILE_NAME");
 | 
						|
    if (PyDict_SetItemString(dict, "INITSCRIPT_ZIP_FILE_NAME",
 | 
						|
            g_InitScriptZipFileName) < 0)
 | 
						|
        return FatalError("unable to set INITSCRIPT_ZIP_FILE_NAME");
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// ExecuteScript()
 | 
						|
//   Execute the script found within the file.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
static int ExecuteScript(
 | 
						|
    const char *fileName)               // name of file containing Python code
 | 
						|
{
 | 
						|
    PyObject *importer, *dict, *code, *temp;
 | 
						|
 | 
						|
    if (SetExecutableName(fileName) < 0)
 | 
						|
        return -1;
 | 
						|
    if (SetPathToSearch() < 0)
 | 
						|
        return -1;
 | 
						|
    importer = NULL;
 | 
						|
    if (GetImporter(&importer) < 0)
 | 
						|
        return -1;
 | 
						|
 | 
						|
    // create and populate dictionary for initscript module
 | 
						|
    dict = PyDict_New();
 | 
						|
    if (PopulateInitScriptDict(dict) < 0) {
 | 
						|
        Py_XDECREF(dict);
 | 
						|
        Py_DECREF(importer);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    // locate and execute script
 | 
						|
    code = PyObject_CallMethod(importer, "get_code", "s", "cx_Freeze__init__");
 | 
						|
    Py_DECREF(importer);
 | 
						|
    if (!code)
 | 
						|
        return FatalError("unable to locate initialization module");
 | 
						|
    temp = PyEval_EvalCode( (PyCodeObject*) code, dict, dict);
 | 
						|
    Py_DECREF(code);
 | 
						|
    Py_DECREF(dict);
 | 
						|
    if (!temp)
 | 
						|
        return FatalScriptError();
 | 
						|
    Py_DECREF(temp);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 |