this repo has no description
at trunk 217 lines 6.5 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include <unistd.h> 3 4#include <climits> 5#include <cstdarg> 6 7#include "cpython-data.h" 8 9#include "api-handle.h" 10#include "list-builtins.h" 11#include "module-builtins.h" 12#include "os.h" 13#include "runtime.h" 14#include "str-builtins.h" 15#include "sys-module.h" 16 17namespace py { 18 19PY_EXPORT size_t _PySys_GetSizeOf(PyObject* o) { 20 Thread* thread = Thread::current(); 21 HandleScope scope(thread); 22 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(o))); 23 Object result_obj(&scope, 24 thread->invokeFunction1(ID(sys), ID(getsizeof), obj)); 25 if (result_obj.isError()) { 26 // Pass through a pending exception if any exists. 27 return static_cast<size_t>(-1); 28 } 29 DCHECK(thread->runtime()->isInstanceOfInt(*result_obj), 30 "sys.getsizeof() should return an int"); 31 Int result(&scope, intUnderlying(*result_obj)); 32 return static_cast<size_t>(result.asWord()); 33} 34 35PY_EXPORT PyObject* PySys_GetObject(const char* name) { 36 DCHECK(name != nullptr, "name must not be nullptr"); 37 Thread* thread = Thread::current(); 38 Runtime* runtime = thread->runtime(); 39 HandleScope scope(thread); 40 Module module(&scope, runtime->findModuleById(ID(sys))); 41 Object name_obj(&scope, Runtime::internStrFromCStr(thread, name)); 42 Object result(&scope, moduleAt(module, name_obj)); 43 if (result.isErrorNotFound()) return nullptr; 44 return ApiHandle::borrowedReference(runtime, *result); 45} 46 47PY_EXPORT void PySys_AddWarnOption(const wchar_t* /* s */) { 48 UNIMPLEMENTED("PySys_AddWarnOption"); 49} 50 51PY_EXPORT void PySys_AddWarnOptionUnicode(PyObject* /* n */) { 52 UNIMPLEMENTED("PySys_AddWarnOptionUnicode"); 53} 54 55PY_EXPORT void PySys_AddXOption(const wchar_t* /* s */) { 56 UNIMPLEMENTED("PySys_AddXOption"); 57} 58 59PY_EXPORT int PySys_Audit(const char* /* event */, const char* /* argFormat */, 60 ...) { 61 return 0; // TODO(T86943617): implement 62} 63 64PY_EXPORT void PySys_FormatStderr(const char* /* t */, ...) { 65 UNIMPLEMENTED("PySys_FormatStderr"); 66} 67 68PY_EXPORT void PySys_FormatStdout(const char* /* t */, ...) { 69 UNIMPLEMENTED("PySys_FormatStdout"); 70} 71 72PY_EXPORT PyObject* PySys_GetXOptions() { UNIMPLEMENTED("PySys_GetXOptions"); } 73 74PY_EXPORT int PySys_HasWarnOptions() { UNIMPLEMENTED("PySys_HasWarnOptions"); } 75 76PY_EXPORT void PySys_ResetWarnOptions() { 77 UNIMPLEMENTED("PySys_ResetWarnOptions"); 78} 79 80static void sysUpdatePath(Thread* thread, const Str& arg0) { 81 Runtime* runtime = thread->runtime(); 82 HandleScope scope(thread); 83 List path(&scope, runtime->lookupNameInModule(thread, ID(sys), ID(path))); 84 85 char* arg0_cstr = arg0.toCStr(); 86 char* script_path = arg0_cstr; 87 88 if (std::strcmp(script_path, "-c") == 0) { 89 Str empty(&scope, Str::empty()); 90 listInsert(thread, path, empty, 0); 91 std::free(arg0_cstr); 92 return; 93 } 94 95 if (std::strcmp(script_path, "-m") == 0) { 96 char buf[PATH_MAX]; 97 if (::getcwd(buf, PATH_MAX) == nullptr) { 98 return; 99 } 100 Str cwd(&scope, runtime->newStrFromCStr(buf)); 101 listInsert(thread, path, cwd, 0); 102 std::free(arg0_cstr); 103 return; 104 } 105 106 char* buf = nullptr; 107 // Follow symlink, if it exists 108 char* link = OS::readLink(script_path); 109 if (link != nullptr) { 110 // It's a symlink 111 if (link[0] == '/') { 112 script_path = link; // Link to absolute path 113 } else if (std::strchr(link, '/') == nullptr) { 114 ; // Link without path 115 } else { 116 // Link has partial path, must join(dirname(script_path), link) 117 char* last_sep = std::strrchr(script_path, '/'); 118 if (last_sep == nullptr) { 119 script_path = link; // script_path has no path 120 } else { 121 // Must make a copy 122 int dir_len = last_sep - script_path + 1; 123 int link_len = std::strlen(link); 124 buf = static_cast<char*>(std::malloc(dir_len + link_len + 1)); 125 std::strncpy(buf, script_path, dir_len); 126 last_sep = buf + (last_sep - script_path); 127 std::strncpy(last_sep + 1, link, link_len + 1); 128 script_path = buf; 129 } 130 } 131 } 132 133 // Resolve the real path. Allow realpath to allocate to avoid PATH_MAX issues 134 char* fullpath = ::realpath(script_path, nullptr); 135 if (fullpath != nullptr) { 136 script_path = fullpath; 137 } 138 139 char* last_sep = std::strrchr(script_path, '/'); 140 word path_len = 0; 141 if (last_sep != nullptr) { 142 path_len = last_sep - script_path + 1; 143 if (path_len > 1) { 144 path_len--; // Drop trailing separator 145 } 146 } 147 148 auto script_path_data = reinterpret_cast<const byte*>(script_path); 149 View<byte> script_path_view(script_path_data, path_len); 150 Object path_element(&scope, runtime->newStrWithAll(script_path_view)); 151 listInsert(thread, path, path_element, 0); 152 153 std::free(fullpath); 154 std::free(link); 155 std::free(buf); 156 std::free(arg0_cstr); 157} 158 159PY_EXPORT void PySys_SetArgv(int argc, wchar_t** argv) { 160 PySys_SetArgvEx(argc, argv, Py_IsolatedFlag == 0); 161} 162 163PY_EXPORT void PySys_SetArgvEx(int argc, wchar_t** argv, int updatepath) { 164 CHECK(argc >= 0, "Unexpected argc"); 165 166 Thread* thread = Thread::current(); 167 Runtime* runtime = thread->runtime(); 168 HandleScope scope(thread); 169 List args(&scope, runtime->newList()); 170 171 Str arg(&scope, Str::empty()); 172 if (argc == 0 || argv == nullptr) { 173 // Ensure at least one (empty) argument is given in sys.argv 174 // This will also ensure the first element of sys.path is an empty string 175 runtime->listAdd(thread, args, arg); 176 } else { 177 for (int i = 0; i < argc; i++) { 178 RawObject result = newStrFromWideChar(thread, argv[i]); 179 CHECK(!result.isErrorException(), "Invalid unicode character in argv"); 180 arg = result; 181 runtime->listAdd(thread, args, arg); 182 } 183 } 184 Module sys_module(&scope, runtime->findModuleById(ID(sys))); 185 moduleAtPutById(thread, sys_module, ID(argv), args); 186 187 if (updatepath == 0) { 188 return; 189 } 190 191 arg = args.at(0); 192 sysUpdatePath(thread, arg); 193} 194 195PY_EXPORT int PySys_SetObject(const char* /* e */, PyObject* /* v */) { 196 UNIMPLEMENTED("PySys_SetObject"); 197} 198 199PY_EXPORT void PySys_SetPath(const wchar_t* /* h */) { 200 UNIMPLEMENTED("PySys_SetPath"); 201} 202 203PY_EXPORT void PySys_WriteStderr(const char* format, ...) { 204 va_list va; 205 va_start(va, format); 206 writeStderrV(Thread::current(), format, va); 207 va_end(va); 208} 209 210PY_EXPORT void PySys_WriteStdout(const char* format, ...) { 211 va_list va; 212 va_start(va, format); 213 writeStdoutV(Thread::current(), format, va); 214 va_end(va); 215} 216 217} // namespace py