1ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// Copyright 2017 Google Inc. All rights reserved. 2ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// 3ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// Licensed under the Apache License, Version 2.0 (the "License"); 4ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// you may not use this file except in compliance with the License. 5ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// You may obtain a copy of the License at 6ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// 7ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// http://www.apache.org/licenses/LICENSE-2.0 8ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// 9ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// Unless required by applicable law or agreed to in writing, software 10ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// distributed under the License is distributed on an "AS IS" BASIS, 11ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// See the License for the specific language governing permissions and 13ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// limitations under the License. 14ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 15ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang#include "launcher_internal.h" 16ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 17ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang#include <limits.h> 18ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang#include <stdio.h> 19ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang#include <stdlib.h> 20ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 21ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangextern "C" { 22ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang// Cpython built-in C functions. 23ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang/* 24ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang read_directory(archive) -> files dict (new reference) 25ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 26ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Given a path to a Zip archive, build a dict, mapping file names 27ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang (local to the archive, using SEP as a separator) to toc entries. 28ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang*/ 29ced27516f5ff24d91382b5e9fb513f0682617a2eNan ZhangPyObject *read_directory(const char *archive); 30ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 31ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang/* Given a path to a Zip file and a toc_entry, return the (uncompressed) 32ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang data as a new reference. */ 33ced27516f5ff24d91382b5e9fb513f0682617a2eNan ZhangPyObject *get_data(const char *archive, PyObject *toc_entry); 34ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} 35ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 36ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangnamespace android { 37ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangnamespace cpython2 { 38ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangnamespace python_launcher { 3933bb4bb92b10c7a34b36085a9c8df6cfe78c0db5Nan Zhangnamespace internal { 40ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 41ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangint RunModule(const char *module, int set_argv0) { 42ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyObject *runpy, *runmodule, *runargs, *result; 43ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang runpy = PyImport_ImportModule("runpy"); 44ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (runpy == NULL) { 45ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang fprintf(stderr, "Could not import runpy module\n"); 46ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 47ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 48ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main"); 49ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (runmodule == NULL) { 50ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang fprintf(stderr, "Could not access runpy._run_module_as_main\n"); 51ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(runpy); 52ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 53ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 54ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang runargs = Py_BuildValue("(si)", module, set_argv0); 55ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (runargs == NULL) { 56ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang fprintf(stderr, 57ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang "Could not create arguments for runpy._run_module_as_main\n"); 58ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(runpy); 59ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(runmodule); 60ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 61ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 62ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang result = PyObject_Call(runmodule, runargs, NULL); 63ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (result == NULL) { 64ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyErr_Print(); 65ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 66ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(runpy); 67ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(runmodule); 68ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(runargs); 69ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (result == NULL) { 70ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 71ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 72ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(result); 73ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return 0; 74ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} 75ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 76ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangstd::string GetEntryPointFilePath(const char *launcher_path) { 77ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyObject *files; 78ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang files = read_directory(launcher_path); 79ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (files == NULL) { 80ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return std::string(); 81ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 82ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyObject *toc_entry; 83ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // Return value: Borrowed reference. 84ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang toc_entry = PyDict_GetItemString(files, ENTRYPOINT_FILE); 85ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (toc_entry == NULL) { 86ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(files); 87ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return std::string(); 88ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 89ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyObject *py_data; 90ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang py_data = get_data(launcher_path, toc_entry); 91ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (py_data == NULL) { 92ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(files); 93ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return std::string(); 94ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 95ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // PyString_AsString returns a NUL-terminated representation of the "py_data", 96ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // "data" must not be modified in any way. And it must not be deallocated. 97ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang char *data = PyString_AsString(py_data); 98ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (data == NULL) { 99ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(py_data); 100ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(files); 101ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return std::string(); 102ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 103ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 104ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang char *res = strdup(data); /* deep copy of data */ 105ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(py_data); 106ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(files); 107ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 108ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang int i = 0; 109ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang /* Strip newline and other trailing whitespace. */ 110ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang for (i = strlen(res) - 1; i >= 0 && isspace(res[i]); i--) { 111ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang res[i] = '\0'; 112ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 113ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang /* Check for the file extension. */ 114ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang i = strlen(res); 115ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (i > 3 && strcmp(res + i - 3, ".py") == 0) { 116ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang res[i - 3] = '\0'; 117ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } else { 118ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyErr_Format(PyExc_ValueError, "Invalid entrypoint in %s: %s", 119ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang ENTRYPOINT_FILE, res); 120ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return std::string(); 121ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 122ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return std::string(res); 123ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} 124ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 125ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangint RunModuleNameFromEntryPoint(const char *launcher_path, std::string entrypoint) { 126ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (entrypoint.empty()) { 127ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 128ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 129ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // Has to pass to free to avoid a memory leak after use. 130ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang char *arr = strdup(entrypoint.c_str()); 131ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // Replace file system path seperator with Python package/module seperator. 132ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang char *ch; 133ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang for (ch = arr; *ch; ch++) { 134ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (*ch == '/') { 135ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang *ch = '.'; 136ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 137ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 138ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 139ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (AddPathToPythonSysPath(launcher_path) < 0) { 140ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang free(arr); 141ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 142ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 143ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // Calculate the runfiles path size. Extra space for '\0'. 144ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang size_t size = snprintf(nullptr, 0, "%s/%s", launcher_path, RUNFILES) + 1; 145ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang char runfiles_path[size]; 146ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang snprintf(runfiles_path, size, "%s/%s", launcher_path, RUNFILES); 147ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (AddPathToPythonSysPath(runfiles_path) < 0) { 148ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang free(arr); 149ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 150ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 151ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang int ret = RunModule(arr, 0); 152ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang free(arr); 153ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return ret; 154ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} 155ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 156ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangint AddPathToPythonSysPath(const char *path) { 157ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (path == NULL) { 158ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 159ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 160ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyObject *py_path; 161ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang py_path = PyString_FromString(path); 162ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (py_path == NULL) { 163ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 164ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 165ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyObject *sys_path; 166ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // Return value: Borrowed reference. 167ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang sys_path = PySys_GetObject(const_cast<char*>("path")); 168ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (sys_path == NULL) { 169ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(py_path); 170ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 171ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 172ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyList_Insert(sys_path, 0, py_path); 173ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(py_path); 174ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return 0; 175ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} 176ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 177ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangint RunMainFromImporter(const char *launcher_path) { 178ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang PyObject *py_launcher_path, *importer; 179ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang py_launcher_path = PyString_FromString(launcher_path); 180ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (py_launcher_path == NULL) { 181ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 182ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 183ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang importer = PyImport_GetImporter(py_launcher_path); 184ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (importer == NULL) { 185ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(py_launcher_path); 186ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 187ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 188ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (importer != Py_None && importer->ob_type != &PyNullImporter_Type) { 189ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang /* Launcher path is usable as an import source, so 190ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang put it in sys.path[0] and import __main__ */ 191ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (AddPathToPythonSysPath(launcher_path) < 0) { 192ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(importer); 193ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(py_launcher_path); 194ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return -1; 195ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 196ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 197ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(importer); 198ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang Py_DECREF(py_launcher_path); 199ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return RunModule("__main__", 0); 200ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} 201ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} // namespace internal 202ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang 203ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhangint RunEntryPointOrMainModule(const char *launcher_path) { 204ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang std::string entrypoint = internal::GetEntryPointFilePath(launcher_path); 205ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang if (entrypoint.empty()) { 206ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // If entry point can not be found or can not be executed, we try to 207ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang // run __main__.py within the .par file. 208ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang fprintf(stderr, "Cannot find valid entry point to execute par file!\n"); 209ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang fprintf(stdout, "Start trying to run __main__ module within par file.\n"); 210ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return internal::RunMainFromImporter(launcher_path); 211ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang } 212ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang return internal::RunModuleNameFromEntryPoint(launcher_path, entrypoint); 213ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} 214ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} // namespace python_launcher 215ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} // namespace cpython2 216ced27516f5ff24d91382b5e9fb513f0682617a2eNan Zhang} // namespace android 217