blob: 24439e019709468483c624f9cad4bf367cc7e9a1 [file] [log] [blame]
Just van Rossum52e14d62002-12-30 22:08:05 +00001#include "Python.h"
2#include "structmember.h"
3#include "osdefs.h"
4#include "marshal.h"
Just van Rossum52e14d62002-12-30 22:08:05 +00005#include <time.h>
6
7
8#define IS_SOURCE 0x0
9#define IS_BYTECODE 0x1
10#define IS_PACKAGE 0x2
11
12struct st_zip_searchorder {
Antoine Pitrouc83ea132010-05-09 14:46:46 +000013 char suffix[14];
14 int type;
Just van Rossum52e14d62002-12-30 22:08:05 +000015};
16
17/* zip_searchorder defines how we search for a module in the Zip
18 archive: we first search for a package __init__, then for
19 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
20 are swapped by initzipimport() if we run in optimized mode. Also,
21 '/' is replaced by SEP there. */
Neal Norwitz29fd2ba2003-03-23 13:21:03 +000022static struct st_zip_searchorder zip_searchorder[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +000023 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
24 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
25 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
26 {".pyc", IS_BYTECODE},
27 {".pyo", IS_BYTECODE},
28 {".py", IS_SOURCE},
29 {"", 0}
Just van Rossum52e14d62002-12-30 22:08:05 +000030};
31
32/* zipimporter object definition and support */
33
34typedef struct _zipimporter ZipImporter;
35
36struct _zipimporter {
Antoine Pitrouc83ea132010-05-09 14:46:46 +000037 PyObject_HEAD
38 PyObject *archive; /* pathname of the Zip archive */
39 PyObject *prefix; /* file prefix: "a/sub/directory/" */
40 PyObject *files; /* dict with file info {path: toc_entry} */
Just van Rossum52e14d62002-12-30 22:08:05 +000041};
42
Just van Rossum52e14d62002-12-30 22:08:05 +000043static PyObject *ZipImportError;
44static PyObject *zip_directory_cache = NULL;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -080045static PyObject *zip_stat_cache = NULL;
46/* posix.fstat or nt.fstat function. Used due to posixmodule.c's
47 * superior fstat implementation over libc's on Windows. */
48static PyObject *fstat_function = NULL; /* posix.fstat() or nt.fstat() */
Just van Rossum52e14d62002-12-30 22:08:05 +000049
50/* forward decls */
Gregory P. Smithb48c5d52014-01-06 09:46:46 -080051static FILE *fopen_rb_and_stat(char *path, PyObject **py_stat_p);
52static FILE *safely_reopen_archive(ZipImporter *self, char **archive_p);
53static PyObject *read_directory(FILE *fp, char *archive);
54static PyObject *get_data(FILE *fp, char *archive, PyObject *toc_entry);
Just van Rossum52e14d62002-12-30 22:08:05 +000055static PyObject *get_module_code(ZipImporter *self, char *fullname,
Antoine Pitrouc83ea132010-05-09 14:46:46 +000056 int *p_ispackage, char **p_modpath);
Just van Rossum52e14d62002-12-30 22:08:05 +000057
58
59#define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type)
60
61
62/* zipimporter.__init__
63 Split the "subdirectory" from the Zip archive path, lookup a matching
64 entry in sys.path_importer_cache, fetch the file directory from there
65 if found, or else read it from the archive. */
66static int
67zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
68{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000069 char *path, *p, *prefix, buf[MAXPATHLEN+2];
70 size_t len;
Just van Rossum52e14d62002-12-30 22:08:05 +000071
Antoine Pitrouc83ea132010-05-09 14:46:46 +000072 if (!_PyArg_NoKeywords("zipimporter()", kwds))
73 return -1;
Georg Brandl02c42872005-08-26 06:42:30 +000074
Antoine Pitrouc83ea132010-05-09 14:46:46 +000075 if (!PyArg_ParseTuple(args, "s:zipimporter",
76 &path))
77 return -1;
Just van Rossum52e14d62002-12-30 22:08:05 +000078
Antoine Pitrouc83ea132010-05-09 14:46:46 +000079 len = strlen(path);
80 if (len == 0) {
81 PyErr_SetString(ZipImportError, "archive path is empty");
82 return -1;
83 }
84 if (len >= MAXPATHLEN) {
85 PyErr_SetString(ZipImportError,
86 "archive path too long");
87 return -1;
88 }
89 strcpy(buf, path);
Just van Rossum52e14d62002-12-30 22:08:05 +000090
91#ifdef ALTSEP
Antoine Pitrouc83ea132010-05-09 14:46:46 +000092 for (p = buf; *p; p++) {
93 if (*p == ALTSEP)
94 *p = SEP;
95 }
Just van Rossum52e14d62002-12-30 22:08:05 +000096#endif
97
Antoine Pitrouc83ea132010-05-09 14:46:46 +000098 path = NULL;
99 prefix = NULL;
100 for (;;) {
Martin v. Löwisa94568a2003-05-10 07:36:56 +0000101#ifndef RISCOS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000102 struct stat statbuf;
103 int rv;
Just van Rossum52e14d62002-12-30 22:08:05 +0000104
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000105 rv = stat(buf, &statbuf);
106 if (rv == 0) {
107 /* it exists */
108 if (S_ISREG(statbuf.st_mode))
109 /* it's a file */
110 path = buf;
111 break;
112 }
Martin v. Löwisa94568a2003-05-10 07:36:56 +0000113#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000114 if (object_exists(buf)) {
115 /* it exists */
116 if (isfile(buf))
117 /* it's a file */
118 path = buf;
119 break;
120 }
Martin v. Löwisa94568a2003-05-10 07:36:56 +0000121#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000122 /* back up one path element */
123 p = strrchr(buf, SEP);
124 if (prefix != NULL)
125 *prefix = SEP;
126 if (p == NULL)
127 break;
128 *p = '\0';
129 prefix = p;
130 }
131 if (path != NULL) {
132 PyObject *files;
133 files = PyDict_GetItemString(zip_directory_cache, path);
134 if (files == NULL) {
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800135 PyObject *zip_stat = NULL;
136 FILE *fp = fopen_rb_and_stat(buf, &zip_stat);
137 if (fp == NULL) {
138 PyErr_Format(ZipImportError, "can't open Zip file: "
139 "'%.200s'", buf);
140 Py_XDECREF(zip_stat);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000141 return -1;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800142 }
143
144 if (Py_VerboseFlag)
145 PySys_WriteStderr("# zipimport: %s not cached, "
146 "reading TOC.\n", path);
147
148 files = read_directory(fp, buf);
149 fclose(fp);
150 if (files == NULL) {
151 Py_XDECREF(zip_stat);
152 return -1;
153 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000154 if (PyDict_SetItemString(zip_directory_cache, path,
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800155 files) != 0) {
156 Py_DECREF(files);
157 Py_XDECREF(zip_stat);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000158 return -1;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800159 }
160 if (zip_stat && PyDict_SetItemString(zip_stat_cache, path,
161 zip_stat) != 0) {
162 Py_DECREF(files);
163 Py_DECREF(zip_stat);
164 return -1;
165 }
166 Py_XDECREF(zip_stat);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000167 }
168 else
169 Py_INCREF(files);
170 self->files = files;
171 }
172 else {
173 PyErr_SetString(ZipImportError, "not a Zip file");
174 return -1;
175 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000176
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000177 if (prefix == NULL)
178 prefix = "";
179 else {
180 prefix++;
181 len = strlen(prefix);
182 if (prefix[len-1] != SEP) {
183 /* add trailing SEP */
184 prefix[len] = SEP;
185 prefix[len + 1] = '\0';
186 }
187 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000188
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000189 self->archive = PyString_FromString(buf);
190 if (self->archive == NULL)
191 return -1;
Just van Rossum52e14d62002-12-30 22:08:05 +0000192
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000193 self->prefix = PyString_FromString(prefix);
194 if (self->prefix == NULL)
195 return -1;
Just van Rossum52e14d62002-12-30 22:08:05 +0000196
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000197 return 0;
Just van Rossum52e14d62002-12-30 22:08:05 +0000198}
199
200/* GC support. */
201static int
202zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
203{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000204 ZipImporter *self = (ZipImporter *)obj;
205 Py_VISIT(self->files);
206 return 0;
Just van Rossum52e14d62002-12-30 22:08:05 +0000207}
208
209static void
210zipimporter_dealloc(ZipImporter *self)
211{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000212 PyObject_GC_UnTrack(self);
213 Py_XDECREF(self->archive);
214 Py_XDECREF(self->prefix);
215 Py_XDECREF(self->files);
216 Py_TYPE(self)->tp_free((PyObject *)self);
Just van Rossum52e14d62002-12-30 22:08:05 +0000217}
218
219static PyObject *
220zipimporter_repr(ZipImporter *self)
221{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000222 char buf[500];
223 char *archive = "???";
224 char *prefix = "";
Just van Rossum52e14d62002-12-30 22:08:05 +0000225
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000226 if (self->archive != NULL && PyString_Check(self->archive))
227 archive = PyString_AsString(self->archive);
228 if (self->prefix != NULL && PyString_Check(self->prefix))
229 prefix = PyString_AsString(self->prefix);
230 if (prefix != NULL && *prefix)
231 PyOS_snprintf(buf, sizeof(buf),
232 "<zipimporter object \"%.300s%c%.150s\">",
233 archive, SEP, prefix);
234 else
235 PyOS_snprintf(buf, sizeof(buf),
236 "<zipimporter object \"%.300s\">",
237 archive);
238 return PyString_FromString(buf);
Just van Rossum52e14d62002-12-30 22:08:05 +0000239}
240
241/* return fullname.split(".")[-1] */
242static char *
243get_subname(char *fullname)
244{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000245 char *subname = strrchr(fullname, '.');
246 if (subname == NULL)
247 subname = fullname;
248 else
249 subname++;
250 return subname;
Just van Rossum52e14d62002-12-30 22:08:05 +0000251}
252
253/* Given a (sub)modulename, write the potential file path in the
254 archive (without extension) to the path buffer. Return the
255 length of the resulting string. */
256static int
257make_filename(char *prefix, char *name, char *path)
258{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000259 size_t len;
260 char *p;
Just van Rossum52e14d62002-12-30 22:08:05 +0000261
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000262 len = strlen(prefix);
Just van Rossum52e14d62002-12-30 22:08:05 +0000263
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000264 /* self.prefix + name [+ SEP + "__init__"] + ".py[co]" */
265 if (len + strlen(name) + 13 >= MAXPATHLEN) {
266 PyErr_SetString(ZipImportError, "path too long");
267 return -1;
268 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000269
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000270 strcpy(path, prefix);
271 strcpy(path + len, name);
272 for (p = path + len; *p; p++) {
273 if (*p == '.')
274 *p = SEP;
275 }
276 len += strlen(name);
277 assert(len < INT_MAX);
278 return (int)len;
Just van Rossum52e14d62002-12-30 22:08:05 +0000279}
280
Raymond Hettinger2c45c9a2004-11-10 13:08:35 +0000281enum zi_module_info {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000282 MI_ERROR,
283 MI_NOT_FOUND,
284 MI_MODULE,
285 MI_PACKAGE
Just van Rossum52e14d62002-12-30 22:08:05 +0000286};
287
288/* Return some information about a module. */
Raymond Hettinger2c45c9a2004-11-10 13:08:35 +0000289static enum zi_module_info
Just van Rossum52e14d62002-12-30 22:08:05 +0000290get_module_info(ZipImporter *self, char *fullname)
291{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000292 char *subname, path[MAXPATHLEN + 1];
293 int len;
294 struct st_zip_searchorder *zso;
Just van Rossum52e14d62002-12-30 22:08:05 +0000295
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000296 subname = get_subname(fullname);
Just van Rossum52e14d62002-12-30 22:08:05 +0000297
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000298 len = make_filename(PyString_AsString(self->prefix), subname, path);
299 if (len < 0)
300 return MI_ERROR;
Just van Rossum52e14d62002-12-30 22:08:05 +0000301
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000302 for (zso = zip_searchorder; *zso->suffix; zso++) {
303 strcpy(path + len, zso->suffix);
304 if (PyDict_GetItemString(self->files, path) != NULL) {
305 if (zso->type & IS_PACKAGE)
306 return MI_PACKAGE;
307 else
308 return MI_MODULE;
309 }
310 }
311 return MI_NOT_FOUND;
Just van Rossum52e14d62002-12-30 22:08:05 +0000312}
313
314/* Check whether we can satisfy the import of the module named by
315 'fullname'. Return self if we can, None if we can't. */
316static PyObject *
317zipimporter_find_module(PyObject *obj, PyObject *args)
318{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000319 ZipImporter *self = (ZipImporter *)obj;
320 PyObject *path = NULL;
321 char *fullname;
322 enum zi_module_info mi;
Just van Rossum52e14d62002-12-30 22:08:05 +0000323
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000324 if (!PyArg_ParseTuple(args, "s|O:zipimporter.find_module",
325 &fullname, &path))
326 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000327
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000328 mi = get_module_info(self, fullname);
329 if (mi == MI_ERROR)
330 return NULL;
331 if (mi == MI_NOT_FOUND) {
332 Py_INCREF(Py_None);
333 return Py_None;
334 }
335 Py_INCREF(self);
336 return (PyObject *)self;
Just van Rossum52e14d62002-12-30 22:08:05 +0000337}
338
339/* Load and return the module named by 'fullname'. */
340static PyObject *
341zipimporter_load_module(PyObject *obj, PyObject *args)
342{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000343 ZipImporter *self = (ZipImporter *)obj;
344 PyObject *code, *mod, *dict;
345 char *fullname, *modpath;
346 int ispackage;
Just van Rossum52e14d62002-12-30 22:08:05 +0000347
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000348 if (!PyArg_ParseTuple(args, "s:zipimporter.load_module",
349 &fullname))
350 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000351
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000352 code = get_module_code(self, fullname, &ispackage, &modpath);
353 if (code == NULL)
354 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000355
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000356 mod = PyImport_AddModule(fullname);
357 if (mod == NULL) {
358 Py_DECREF(code);
359 return NULL;
360 }
361 dict = PyModule_GetDict(mod);
Just van Rossum52e14d62002-12-30 22:08:05 +0000362
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000363 /* mod.__loader__ = self */
364 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
365 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000366
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000367 if (ispackage) {
368 /* add __path__ to the module *before* the code gets
369 executed */
370 PyObject *pkgpath, *fullpath;
371 char *prefix = PyString_AsString(self->prefix);
372 char *subname = get_subname(fullname);
373 int err;
Just van Rossum52e14d62002-12-30 22:08:05 +0000374
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000375 fullpath = PyString_FromFormat("%s%c%s%s",
376 PyString_AsString(self->archive),
377 SEP,
378 *prefix ? prefix : "",
379 subname);
380 if (fullpath == NULL)
381 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000382
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000383 pkgpath = Py_BuildValue("[O]", fullpath);
384 Py_DECREF(fullpath);
385 if (pkgpath == NULL)
386 goto error;
387 err = PyDict_SetItemString(dict, "__path__", pkgpath);
388 Py_DECREF(pkgpath);
389 if (err != 0)
390 goto error;
391 }
392 mod = PyImport_ExecCodeModuleEx(fullname, code, modpath);
393 Py_DECREF(code);
394 if (Py_VerboseFlag)
395 PySys_WriteStderr("import %s # loaded from Zip %s\n",
396 fullname, modpath);
397 return mod;
Just van Rossum52e14d62002-12-30 22:08:05 +0000398error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000399 Py_DECREF(code);
400 Py_DECREF(mod);
401 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000402}
403
Nick Coghlana2053472008-12-14 10:54:50 +0000404/* Return a string matching __file__ for the named module */
405static PyObject *
406zipimporter_get_filename(PyObject *obj, PyObject *args)
407{
408 ZipImporter *self = (ZipImporter *)obj;
409 PyObject *code;
410 char *fullname, *modpath;
411 int ispackage;
412
Nick Coghlan0194f5b2009-02-08 03:17:00 +0000413 if (!PyArg_ParseTuple(args, "s:zipimporter.get_filename",
Nick Coghlana2053472008-12-14 10:54:50 +0000414 &fullname))
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000415 return NULL;
Nick Coghlana2053472008-12-14 10:54:50 +0000416
417 /* Deciding the filename requires working out where the code
418 would come from if the module was actually loaded */
419 code = get_module_code(self, fullname, &ispackage, &modpath);
420 if (code == NULL)
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000421 return NULL;
Nick Coghlana2053472008-12-14 10:54:50 +0000422 Py_DECREF(code); /* Only need the path info */
423
424 return PyString_FromString(modpath);
425}
426
Just van Rossum52e14d62002-12-30 22:08:05 +0000427/* Return a bool signifying whether the module is a package or not. */
428static PyObject *
429zipimporter_is_package(PyObject *obj, PyObject *args)
430{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000431 ZipImporter *self = (ZipImporter *)obj;
432 char *fullname;
433 enum zi_module_info mi;
Just van Rossum52e14d62002-12-30 22:08:05 +0000434
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000435 if (!PyArg_ParseTuple(args, "s:zipimporter.is_package",
436 &fullname))
437 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000438
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000439 mi = get_module_info(self, fullname);
440 if (mi == MI_ERROR)
441 return NULL;
442 if (mi == MI_NOT_FOUND) {
443 PyErr_Format(ZipImportError, "can't find module '%.200s'",
444 fullname);
445 return NULL;
446 }
447 return PyBool_FromLong(mi == MI_PACKAGE);
Just van Rossum52e14d62002-12-30 22:08:05 +0000448}
449
450static PyObject *
451zipimporter_get_data(PyObject *obj, PyObject *args)
452{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000453 ZipImporter *self = (ZipImporter *)obj;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800454 char *path, *archive;
455 FILE *fp;
Just van Rossum52e14d62002-12-30 22:08:05 +0000456#ifdef ALTSEP
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000457 char *p, buf[MAXPATHLEN + 1];
Just van Rossum52e14d62002-12-30 22:08:05 +0000458#endif
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800459 PyObject *toc_entry, *data;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000460 Py_ssize_t len;
Just van Rossum52e14d62002-12-30 22:08:05 +0000461
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000462 if (!PyArg_ParseTuple(args, "s:zipimporter.get_data", &path))
463 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000464
465#ifdef ALTSEP
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000466 if (strlen(path) >= MAXPATHLEN) {
467 PyErr_SetString(ZipImportError, "path too long");
468 return NULL;
469 }
470 strcpy(buf, path);
471 for (p = buf; *p; p++) {
472 if (*p == ALTSEP)
473 *p = SEP;
474 }
475 path = buf;
Just van Rossum52e14d62002-12-30 22:08:05 +0000476#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000477 len = PyString_Size(self->archive);
478 if ((size_t)len < strlen(path) &&
479 strncmp(path, PyString_AsString(self->archive), len) == 0 &&
480 path[len] == SEP) {
481 path = path + len + 1;
482 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000483
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800484 fp = safely_reopen_archive(self, &archive);
485 if (fp == NULL)
486 return NULL;
487
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000488 toc_entry = PyDict_GetItemString(self->files, path);
489 if (toc_entry == NULL) {
490 PyErr_SetFromErrnoWithFilename(PyExc_IOError, path);
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800491 fclose(fp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000492 return NULL;
493 }
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800494 data = get_data(fp, archive, toc_entry);
495 fclose(fp);
496 return data;
Just van Rossum52e14d62002-12-30 22:08:05 +0000497}
498
499static PyObject *
500zipimporter_get_code(PyObject *obj, PyObject *args)
501{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000502 ZipImporter *self = (ZipImporter *)obj;
503 char *fullname;
Just van Rossum52e14d62002-12-30 22:08:05 +0000504
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000505 if (!PyArg_ParseTuple(args, "s:zipimporter.get_code", &fullname))
506 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000507
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000508 return get_module_code(self, fullname, NULL, NULL);
Just van Rossum52e14d62002-12-30 22:08:05 +0000509}
510
511static PyObject *
512zipimporter_get_source(PyObject *obj, PyObject *args)
513{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000514 ZipImporter *self = (ZipImporter *)obj;
515 PyObject *toc_entry;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800516 FILE *fp;
517 char *fullname, *subname, path[MAXPATHLEN+1], *archive;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000518 int len;
519 enum zi_module_info mi;
Just van Rossum52e14d62002-12-30 22:08:05 +0000520
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000521 if (!PyArg_ParseTuple(args, "s:zipimporter.get_source", &fullname))
522 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000523
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000524 mi = get_module_info(self, fullname);
525 if (mi == MI_ERROR)
526 return NULL;
527 if (mi == MI_NOT_FOUND) {
528 PyErr_Format(ZipImportError, "can't find module '%.200s'",
529 fullname);
530 return NULL;
531 }
532 subname = get_subname(fullname);
Just van Rossum52e14d62002-12-30 22:08:05 +0000533
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000534 len = make_filename(PyString_AsString(self->prefix), subname, path);
535 if (len < 0)
536 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000537
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000538 if (mi == MI_PACKAGE) {
539 path[len] = SEP;
540 strcpy(path + len + 1, "__init__.py");
541 }
542 else
543 strcpy(path + len, ".py");
Just van Rossum52e14d62002-12-30 22:08:05 +0000544
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800545 fp = safely_reopen_archive(self, &archive);
546 if (fp == NULL)
547 return NULL;
548
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000549 toc_entry = PyDict_GetItemString(self->files, path);
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800550 if (toc_entry != NULL) {
551 PyObject *data = get_data(fp, archive, toc_entry);
552 fclose(fp);
553 return data;
554 }
555 fclose(fp);
Just van Rossum52e14d62002-12-30 22:08:05 +0000556
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000557 /* we have the module, but no source */
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800558 Py_RETURN_NONE;
Just van Rossum52e14d62002-12-30 22:08:05 +0000559}
560
561PyDoc_STRVAR(doc_find_module,
562"find_module(fullname, path=None) -> self or None.\n\
563\n\
564Search for a module specified by 'fullname'. 'fullname' must be the\n\
565fully qualified (dotted) module name. It returns the zipimporter\n\
566instance itself if the module was found, or None if it wasn't.\n\
567The optional 'path' argument is ignored -- it's there for compatibility\n\
568with the importer protocol.");
569
570PyDoc_STRVAR(doc_load_module,
571"load_module(fullname) -> module.\n\
572\n\
573Load the module specified by 'fullname'. 'fullname' must be the\n\
574fully qualified (dotted) module name. It returns the imported\n\
575module, or raises ZipImportError if it wasn't found.");
576
577PyDoc_STRVAR(doc_get_data,
578"get_data(pathname) -> string with file data.\n\
579\n\
580Return the data associated with 'pathname'. Raise IOError if\n\
581the file wasn't found.");
582
583PyDoc_STRVAR(doc_is_package,
584"is_package(fullname) -> bool.\n\
585\n\
586Return True if the module specified by fullname is a package.\n\
Brian Curtin13b43e72010-07-21 01:35:46 +0000587Raise ZipImportError if the module couldn't be found.");
Just van Rossum52e14d62002-12-30 22:08:05 +0000588
589PyDoc_STRVAR(doc_get_code,
590"get_code(fullname) -> code object.\n\
591\n\
592Return the code object for the specified module. Raise ZipImportError\n\
Brian Curtin13b43e72010-07-21 01:35:46 +0000593if the module couldn't be found.");
Just van Rossum52e14d62002-12-30 22:08:05 +0000594
595PyDoc_STRVAR(doc_get_source,
596"get_source(fullname) -> source string.\n\
597\n\
598Return the source code for the specified module. Raise ZipImportError\n\
Brian Curtin13b43e72010-07-21 01:35:46 +0000599if the module couldn't be found, return None if the archive does\n\
Just van Rossum52e14d62002-12-30 22:08:05 +0000600contain the module, but has no source for it.");
601
Nick Coghlana2053472008-12-14 10:54:50 +0000602
603PyDoc_STRVAR(doc_get_filename,
Nick Coghlan0194f5b2009-02-08 03:17:00 +0000604"get_filename(fullname) -> filename string.\n\
Nick Coghlana2053472008-12-14 10:54:50 +0000605\n\
606Return the filename for the specified module.");
607
Just van Rossum52e14d62002-12-30 22:08:05 +0000608static PyMethodDef zipimporter_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000609 {"find_module", zipimporter_find_module, METH_VARARGS,
610 doc_find_module},
611 {"load_module", zipimporter_load_module, METH_VARARGS,
612 doc_load_module},
613 {"get_data", zipimporter_get_data, METH_VARARGS,
614 doc_get_data},
615 {"get_code", zipimporter_get_code, METH_VARARGS,
616 doc_get_code},
617 {"get_source", zipimporter_get_source, METH_VARARGS,
618 doc_get_source},
619 {"get_filename", zipimporter_get_filename, METH_VARARGS,
620 doc_get_filename},
621 {"is_package", zipimporter_is_package, METH_VARARGS,
622 doc_is_package},
623 {NULL, NULL} /* sentinel */
Just van Rossum52e14d62002-12-30 22:08:05 +0000624};
625
626static PyMemberDef zipimporter_members[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000627 {"archive", T_OBJECT, offsetof(ZipImporter, archive), READONLY},
628 {"prefix", T_OBJECT, offsetof(ZipImporter, prefix), READONLY},
629 {"_files", T_OBJECT, offsetof(ZipImporter, files), READONLY},
630 {NULL}
Just van Rossum52e14d62002-12-30 22:08:05 +0000631};
632
633PyDoc_STRVAR(zipimporter_doc,
634"zipimporter(archivepath) -> zipimporter object\n\
635\n\
636Create a new zipimporter instance. 'archivepath' must be a path to\n\
Georg Brandl6a57c082008-05-11 15:05:13 +0000637a zipfile, or to a specific path inside a zipfile. For example, it can be\n\
638'/tmp/myimport.zip', or '/tmp/myimport.zip/mydirectory', if mydirectory is a\n\
639valid directory inside the archive.\n\
640\n\
641'ZipImportError is raised if 'archivepath' doesn't point to a valid Zip\n\
642archive.\n\
643\n\
644The 'archive' attribute of zipimporter objects contains the name of the\n\
645zipfile targeted.");
Just van Rossum52e14d62002-12-30 22:08:05 +0000646
647#define DEFERRED_ADDRESS(ADDR) 0
648
649static PyTypeObject ZipImporter_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000650 PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
651 "zipimport.zipimporter",
652 sizeof(ZipImporter),
653 0, /* tp_itemsize */
654 (destructor)zipimporter_dealloc, /* tp_dealloc */
655 0, /* tp_print */
656 0, /* tp_getattr */
657 0, /* tp_setattr */
658 0, /* tp_compare */
659 (reprfunc)zipimporter_repr, /* tp_repr */
660 0, /* tp_as_number */
661 0, /* tp_as_sequence */
662 0, /* tp_as_mapping */
663 0, /* tp_hash */
664 0, /* tp_call */
665 0, /* tp_str */
666 PyObject_GenericGetAttr, /* tp_getattro */
667 0, /* tp_setattro */
668 0, /* tp_as_buffer */
669 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
670 Py_TPFLAGS_HAVE_GC, /* tp_flags */
671 zipimporter_doc, /* tp_doc */
672 zipimporter_traverse, /* tp_traverse */
673 0, /* tp_clear */
674 0, /* tp_richcompare */
675 0, /* tp_weaklistoffset */
676 0, /* tp_iter */
677 0, /* tp_iternext */
678 zipimporter_methods, /* tp_methods */
679 zipimporter_members, /* tp_members */
680 0, /* tp_getset */
681 0, /* tp_base */
682 0, /* tp_dict */
683 0, /* tp_descr_get */
684 0, /* tp_descr_set */
685 0, /* tp_dictoffset */
686 (initproc)zipimporter_init, /* tp_init */
687 PyType_GenericAlloc, /* tp_alloc */
688 PyType_GenericNew, /* tp_new */
689 PyObject_GC_Del, /* tp_free */
Just van Rossum52e14d62002-12-30 22:08:05 +0000690};
691
692
693/* implementation */
694
Just van Rossum52e14d62002-12-30 22:08:05 +0000695/* Given a buffer, return the long that is represented by the first
696 4 bytes, encoded as little endian. This partially reimplements
697 marshal.c:r_long() */
698static long
699get_long(unsigned char *buf) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000700 long x;
701 x = buf[0];
702 x |= (long)buf[1] << 8;
703 x |= (long)buf[2] << 16;
704 x |= (long)buf[3] << 24;
Just van Rossum52e14d62002-12-30 22:08:05 +0000705#if SIZEOF_LONG > 4
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000706 /* Sign extension for 64-bit machines */
707 x |= -(x & 0x80000000L);
Just van Rossum52e14d62002-12-30 22:08:05 +0000708#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000709 return x;
Just van Rossum52e14d62002-12-30 22:08:05 +0000710}
711
712/*
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800713 fopen_rb_and_stat(path, &py_stat) -> FILE *
714
715 Opens path in "rb" mode and populates the Python py_stat stat_result
716 with information about the opened file. *py_stat may not be changed
717 if there is no fstat_function or if fstat_function fails.
718
719 Returns NULL and does nothing to *py_stat if the open failed.
720*/
721static FILE *
722fopen_rb_and_stat(char *path, PyObject **py_stat_p)
723{
724 FILE *fp;
725 assert(py_stat_p != NULL);
726 assert(*py_stat_p == NULL);
727
728 fp = fopen(path, "rb");
729 if (fp == NULL) {
730 return NULL;
731 }
732
733 if (fstat_function) {
734 PyObject *stat_result = PyObject_CallFunction(fstat_function,
735 "i", fileno(fp));
736 if (stat_result == NULL) {
737 PyErr_Clear(); /* We can function without it. */
738 } else {
739 *py_stat_p = stat_result;
740 }
741 }
742
743 return fp;
744}
745
746/* Return 1 if objects a and b fail a Py_EQ test for an attr. */
747static int
748compare_obj_attr_strings(PyObject *obj_a, PyObject *obj_b, char *attr_name)
749{
750 int problem = 0;
751 PyObject *attr_a = PyObject_GetAttrString(obj_a, attr_name);
752 PyObject *attr_b = PyObject_GetAttrString(obj_b, attr_name);
753 if (attr_a == NULL || attr_b == NULL)
754 problem = 1;
755 else
756 problem = (PyObject_RichCompareBool(attr_a, attr_b, Py_EQ) != 1);
757 Py_XDECREF(attr_a);
758 Py_XDECREF(attr_b);
759 return problem;
760}
761
762/*
763 * Returns an open FILE * on success and sets *archive_p to point to
764 * a read only C string representation of the archive name (as a
765 * convenience for use in error messages).
766 *
767 * Returns NULL on error with the Python error context set.
768 */
769static FILE *
770safely_reopen_archive(ZipImporter *self, char **archive_p)
771{
772 FILE *fp;
773 PyObject *stat_now = NULL;
774 char *archive;
775
776 assert(archive_p != NULL);
777 *archive_p = PyString_AsString(self->archive);
778 if (*archive_p == NULL)
779 return NULL;
780 archive = *archive_p;
781
782 fp = fopen_rb_and_stat(archive, &stat_now);
783 if (!fp) {
784 PyErr_Format(PyExc_IOError,
785 "zipimport: can not open file %s", archive);
786 Py_XDECREF(stat_now);
787 return NULL;
788 }
789
790 if (stat_now != NULL) {
791 int problem = 0;
792 PyObject *files;
793 PyObject *prev_stat = PyDict_GetItemString(zip_stat_cache, archive);
794 /* Test stat_now vs the old cached stat on some key attributes. */
795 if (prev_stat != NULL) {
796 problem = compare_obj_attr_strings(prev_stat, stat_now,
797 "st_ino");
798 problem |= compare_obj_attr_strings(prev_stat, stat_now,
799 "st_size");
800 problem |= compare_obj_attr_strings(prev_stat, stat_now,
801 "st_mtime");
802 } else {
803 if (Py_VerboseFlag)
804 PySys_WriteStderr("# zipimport: no stat data for %s!\n",
805 archive);
806 problem = 1;
807 }
808
809 if (problem) {
810 if (Py_VerboseFlag)
811 PySys_WriteStderr("# zipimport: %s modified since last"
812 " import, rereading TOC.\n", archive);
813 files = read_directory(fp, archive);
814 if (files == NULL) {
815 Py_DECREF(stat_now);
816 fclose(fp);
817 return NULL;
818 }
819 if (PyDict_SetItem(zip_directory_cache, self->archive,
820 files) != 0) {
821 Py_DECREF(files);
822 Py_DECREF(stat_now);
823 fclose(fp);
824 return NULL;
825 }
826 if (stat_now && PyDict_SetItem(zip_stat_cache, self->archive,
827 stat_now) != 0) {
828 Py_DECREF(files);
829 Py_DECREF(stat_now);
830 fclose(fp);
831 return NULL;
832 }
833 Py_XDECREF(self->files); /* free the old value. */
834 self->files = files;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800835 }
Benjamin Peterson7251fe12014-01-09 09:36:10 -0600836 Py_DECREF(stat_now);
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800837 } /* stat succeeded */
838
839 return fp;
840}
841
842/*
843 read_directory(fp, archive) -> files dict (new reference)
Just van Rossum52e14d62002-12-30 22:08:05 +0000844
845 Given a path to a Zip archive, build a dict, mapping file names
846 (local to the archive, using SEP as a separator) to toc entries.
847
848 A toc_entry is a tuple:
849
Fred Drakef5b7fd22005-11-11 19:34:56 +0000850 (__file__, # value to use for __file__, available for all files
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000851 compress, # compression kind; 0 for uncompressed
852 data_size, # size of compressed data on disk
853 file_size, # size of decompressed data
854 file_offset, # offset of file header from start of archive
855 time, # mod time of file (in dos format)
856 date, # mod data of file (in dos format)
857 crc, # crc checksum of the data
Just van Rossum52e14d62002-12-30 22:08:05 +0000858 )
859
860 Directories can be recognized by the trailing SEP in the name,
861 data_size and file_offset are 0.
862*/
863static PyObject *
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800864read_directory(FILE *fp, char *archive)
Just van Rossum52e14d62002-12-30 22:08:05 +0000865{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000866 PyObject *files = NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000867 long compress, crc, data_size, file_size, file_offset, date, time;
868 long header_offset, name_size, header_size, header_position;
869 long i, l, count;
870 size_t length;
871 char path[MAXPATHLEN + 5];
872 char name[MAXPATHLEN + 5];
873 char *p, endof_central_dir[22];
874 long arc_offset; /* offset from beginning of file to start of zip-archive */
Just van Rossum52e14d62002-12-30 22:08:05 +0000875
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800876 assert(fp != NULL);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000877 if (strlen(archive) > MAXPATHLEN) {
878 PyErr_SetString(PyExc_OverflowError,
879 "Zip path name is too long");
880 return NULL;
881 }
882 strcpy(path, archive);
Just van Rossum52e14d62002-12-30 22:08:05 +0000883
Jesus Ceae884be62012-10-03 02:13:05 +0200884 if (fseek(fp, -22, SEEK_END) == -1) {
Jesus Ceae884be62012-10-03 02:13:05 +0200885 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
886 return NULL;
887 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000888 header_position = ftell(fp);
889 if (fread(endof_central_dir, 1, 22, fp) != 22) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000890 PyErr_Format(ZipImportError, "can't read Zip file: "
891 "'%.200s'", archive);
892 return NULL;
893 }
894 if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
895 /* Bad: End of Central Dir signature */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000896 PyErr_Format(ZipImportError, "not a Zip file: "
897 "'%.200s'", archive);
898 return NULL;
899 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000900
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000901 header_size = get_long((unsigned char *)endof_central_dir + 12);
902 header_offset = get_long((unsigned char *)endof_central_dir + 16);
903 arc_offset = header_position - header_offset - header_size;
904 header_offset += arc_offset;
Just van Rossum52e14d62002-12-30 22:08:05 +0000905
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000906 files = PyDict_New();
907 if (files == NULL)
908 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000909
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000910 length = (long)strlen(path);
911 path[length] = SEP;
Just van Rossum52e14d62002-12-30 22:08:05 +0000912
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000913 /* Start of Central Directory */
914 count = 0;
915 for (;;) {
916 PyObject *t;
917 int err;
Just van Rossum52e14d62002-12-30 22:08:05 +0000918
Jesus Ceae884be62012-10-03 02:13:05 +0200919 if (fseek(fp, header_offset, 0) == -1) /* Start of file header */
920 goto fseek_error;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000921 l = PyMarshal_ReadLongFromFile(fp);
922 if (l != 0x02014B50)
923 break; /* Bad: Central Dir File Header */
Jesus Ceae884be62012-10-03 02:13:05 +0200924 if (fseek(fp, header_offset + 10, 0) == -1)
925 goto fseek_error;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000926 compress = PyMarshal_ReadShortFromFile(fp);
927 time = PyMarshal_ReadShortFromFile(fp);
928 date = PyMarshal_ReadShortFromFile(fp);
929 crc = PyMarshal_ReadLongFromFile(fp);
930 data_size = PyMarshal_ReadLongFromFile(fp);
931 file_size = PyMarshal_ReadLongFromFile(fp);
932 name_size = PyMarshal_ReadShortFromFile(fp);
933 header_size = 46 + name_size +
934 PyMarshal_ReadShortFromFile(fp) +
935 PyMarshal_ReadShortFromFile(fp);
Jesus Ceae884be62012-10-03 02:13:05 +0200936 if (fseek(fp, header_offset + 42, 0) == -1)
937 goto fseek_error;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000938 file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
939 if (name_size > MAXPATHLEN)
940 name_size = MAXPATHLEN;
Just van Rossum52e14d62002-12-30 22:08:05 +0000941
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000942 p = name;
943 for (i = 0; i < name_size; i++) {
944 *p = (char)getc(fp);
945 if (*p == '/')
946 *p = SEP;
947 p++;
948 }
949 *p = 0; /* Add terminating null byte */
950 header_offset += header_size;
Just van Rossum52e14d62002-12-30 22:08:05 +0000951
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000952 strncpy(path + length + 1, name, MAXPATHLEN - length - 1);
Just van Rossum52e14d62002-12-30 22:08:05 +0000953
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000954 t = Py_BuildValue("siiiiiii", path, compress, data_size,
955 file_size, file_offset, time, date, crc);
956 if (t == NULL)
957 goto error;
958 err = PyDict_SetItemString(files, name, t);
959 Py_DECREF(t);
960 if (err != 0)
961 goto error;
962 count++;
963 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000964 if (Py_VerboseFlag)
965 PySys_WriteStderr("# zipimport: found %ld names in %s\n",
966 count, archive);
967 return files;
Jesus Ceae884be62012-10-03 02:13:05 +0200968fseek_error:
Jesus Ceae884be62012-10-03 02:13:05 +0200969 Py_XDECREF(files);
970 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
971 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000972error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000973 Py_XDECREF(files);
974 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000975}
976
977/* Return the zlib.decompress function object, or NULL if zlib couldn't
978 be imported. The function is cached when found, so subsequent calls
Victor Stinnerf58f1c32011-05-21 02:13:22 +0200979 don't import zlib again. */
Just van Rossum52e14d62002-12-30 22:08:05 +0000980static PyObject *
981get_decompress_func(void)
982{
Victor Stinnerf58f1c32011-05-21 02:13:22 +0200983 static int importing_zlib = 0;
984 PyObject *zlib;
985 PyObject *decompress;
Just van Rossum52e14d62002-12-30 22:08:05 +0000986
Victor Stinnerf58f1c32011-05-21 02:13:22 +0200987 if (importing_zlib != 0)
988 /* Someone has a zlib.py[co] in their Zip file;
989 let's avoid a stack overflow. */
990 return NULL;
991 importing_zlib = 1;
992 zlib = PyImport_ImportModuleNoBlock("zlib");
993 importing_zlib = 0;
994 if (zlib != NULL) {
995 decompress = PyObject_GetAttrString(zlib,
996 "decompress");
997 Py_DECREF(zlib);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000998 }
Victor Stinnerf58f1c32011-05-21 02:13:22 +0200999 else {
1000 PyErr_Clear();
1001 decompress = NULL;
1002 }
1003 if (Py_VerboseFlag)
1004 PySys_WriteStderr("# zipimport: zlib %s\n",
1005 zlib != NULL ? "available": "UNAVAILABLE");
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001006 return decompress;
Just van Rossum52e14d62002-12-30 22:08:05 +00001007}
1008
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001009/* Given a FILE* to a Zip file and a toc_entry, return the (uncompressed)
Just van Rossum52e14d62002-12-30 22:08:05 +00001010 data as a new reference. */
1011static PyObject *
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001012get_data(FILE *fp, char *archive, PyObject *toc_entry)
Just van Rossum52e14d62002-12-30 22:08:05 +00001013{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001014 PyObject *raw_data, *data = NULL, *decompress;
1015 char *buf;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001016 int err;
1017 Py_ssize_t bytes_read = 0;
1018 long l;
1019 char *datapath;
1020 long compress, data_size, file_size, file_offset;
1021 long time, date, crc;
Just van Rossum52e14d62002-12-30 22:08:05 +00001022
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001023 if (!PyArg_ParseTuple(toc_entry, "slllllll", &datapath, &compress,
1024 &data_size, &file_size, &file_offset, &time,
1025 &date, &crc)) {
1026 return NULL;
1027 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001028
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001029 /* Check to make sure the local file header is correct */
Jesus Ceae884be62012-10-03 02:13:05 +02001030 if (fseek(fp, file_offset, 0) == -1) {
Jesus Ceae884be62012-10-03 02:13:05 +02001031 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
1032 return NULL;
1033 }
1034
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001035 l = PyMarshal_ReadLongFromFile(fp);
1036 if (l != 0x04034B50) {
1037 /* Bad: Local File Header */
1038 PyErr_Format(ZipImportError,
1039 "bad local file header in %s",
1040 archive);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001041 return NULL;
1042 }
Jesus Ceae884be62012-10-03 02:13:05 +02001043 if (fseek(fp, file_offset + 26, 0) == -1) {
Jesus Ceae884be62012-10-03 02:13:05 +02001044 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
1045 return NULL;
1046 }
1047
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001048 l = 30 + PyMarshal_ReadShortFromFile(fp) +
1049 PyMarshal_ReadShortFromFile(fp); /* local header size */
1050 file_offset += l; /* Start of file data */
Just van Rossum52e14d62002-12-30 22:08:05 +00001051
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001052 raw_data = PyString_FromStringAndSize((char *)NULL, compress == 0 ?
1053 data_size : data_size + 1);
1054 if (raw_data == NULL) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001055 return NULL;
1056 }
1057 buf = PyString_AsString(raw_data);
Just van Rossum52e14d62002-12-30 22:08:05 +00001058
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001059 err = fseek(fp, file_offset, 0);
Jesus Ceae884be62012-10-03 02:13:05 +02001060 if (err == 0) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001061 bytes_read = fread(buf, 1, data_size, fp);
Jesus Ceae884be62012-10-03 02:13:05 +02001062 } else {
Jesus Ceae884be62012-10-03 02:13:05 +02001063 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
1064 return NULL;
1065 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001066 if (err || bytes_read != data_size) {
1067 PyErr_SetString(PyExc_IOError,
1068 "zipimport: can't read data");
1069 Py_DECREF(raw_data);
1070 return NULL;
1071 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001072
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001073 if (compress != 0) {
1074 buf[data_size] = 'Z'; /* saw this in zipfile.py */
1075 data_size++;
1076 }
1077 buf[data_size] = '\0';
Just van Rossum52e14d62002-12-30 22:08:05 +00001078
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001079 if (compress == 0) /* data is not compressed */
1080 return raw_data;
Just van Rossum52e14d62002-12-30 22:08:05 +00001081
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001082 /* Decompress with zlib */
1083 decompress = get_decompress_func();
1084 if (decompress == NULL) {
1085 PyErr_SetString(ZipImportError,
1086 "can't decompress data; "
1087 "zlib not available");
1088 goto error;
1089 }
1090 data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
Victor Stinnerf58f1c32011-05-21 02:13:22 +02001091 Py_DECREF(decompress);
Just van Rossum52e14d62002-12-30 22:08:05 +00001092error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001093 Py_DECREF(raw_data);
1094 return data;
Just van Rossum52e14d62002-12-30 22:08:05 +00001095}
1096
1097/* Lenient date/time comparison function. The precision of the mtime
1098 in the archive is lower than the mtime stored in a .pyc: we
1099 must allow a difference of at most one second. */
1100static int
1101eq_mtime(time_t t1, time_t t2)
1102{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001103 time_t d = t1 - t2;
1104 if (d < 0)
1105 d = -d;
1106 /* dostime only stores even seconds, so be lenient */
1107 return d <= 1;
Just van Rossum52e14d62002-12-30 22:08:05 +00001108}
1109
1110/* Given the contents of a .py[co] file in a buffer, unmarshal the data
1111 and return the code object. Return None if it the magic word doesn't
1112 match (we do this instead of raising an exception as we fall back
1113 to .py if available and we don't want to mask other errors).
1114 Returns a new reference. */
1115static PyObject *
1116unmarshal_code(char *pathname, PyObject *data, time_t mtime)
1117{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001118 PyObject *code;
1119 char *buf = PyString_AsString(data);
1120 Py_ssize_t size = PyString_Size(data);
Just van Rossum52e14d62002-12-30 22:08:05 +00001121
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001122 if (size <= 9) {
1123 PyErr_SetString(ZipImportError,
1124 "bad pyc data");
1125 return NULL;
1126 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001127
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001128 if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {
1129 if (Py_VerboseFlag)
1130 PySys_WriteStderr("# %s has bad magic\n",
1131 pathname);
1132 Py_INCREF(Py_None);
1133 return Py_None; /* signal caller to try alternative */
1134 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001135
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001136 if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),
1137 mtime)) {
1138 if (Py_VerboseFlag)
1139 PySys_WriteStderr("# %s has bad mtime\n",
1140 pathname);
1141 Py_INCREF(Py_None);
1142 return Py_None; /* signal caller to try alternative */
1143 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001144
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001145 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
1146 if (code == NULL)
1147 return NULL;
1148 if (!PyCode_Check(code)) {
1149 Py_DECREF(code);
1150 PyErr_Format(PyExc_TypeError,
1151 "compiled module %.200s is not a code object",
1152 pathname);
1153 return NULL;
1154 }
1155 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001156}
1157
1158/* Replace any occurances of "\r\n?" in the input string with "\n".
1159 This converts DOS and Mac line endings to Unix line endings.
1160 Also append a trailing "\n" to be compatible with
1161 PyParser_SimpleParseFile(). Returns a new reference. */
1162static PyObject *
1163normalize_line_endings(PyObject *source)
1164{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001165 char *buf, *q, *p = PyString_AsString(source);
1166 PyObject *fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001167
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001168 if (!p)
1169 return NULL;
Neal Norwitzee7c8f92006-08-13 18:12:03 +00001170
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001171 /* one char extra for trailing \n and one for terminating \0 */
1172 buf = (char *)PyMem_Malloc(PyString_Size(source) + 2);
1173 if (buf == NULL) {
1174 PyErr_SetString(PyExc_MemoryError,
1175 "zipimport: no memory to allocate "
1176 "source buffer");
1177 return NULL;
1178 }
1179 /* replace "\r\n?" by "\n" */
1180 for (q = buf; *p != '\0'; p++) {
1181 if (*p == '\r') {
1182 *q++ = '\n';
1183 if (*(p + 1) == '\n')
1184 p++;
1185 }
1186 else
1187 *q++ = *p;
1188 }
1189 *q++ = '\n'; /* add trailing \n */
1190 *q = '\0';
1191 fixed_source = PyString_FromString(buf);
1192 PyMem_Free(buf);
1193 return fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001194}
1195
1196/* Given a string buffer containing Python source code, compile it
1197 return and return a code object as a new reference. */
1198static PyObject *
1199compile_source(char *pathname, PyObject *source)
1200{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001201 PyObject *code, *fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001202
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001203 fixed_source = normalize_line_endings(source);
1204 if (fixed_source == NULL)
1205 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001206
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001207 code = Py_CompileString(PyString_AsString(fixed_source), pathname,
1208 Py_file_input);
1209 Py_DECREF(fixed_source);
1210 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001211}
1212
1213/* Convert the date/time values found in the Zip archive to a value
1214 that's compatible with the time stamp stored in .pyc files. */
Neal Norwitz29fd2ba2003-03-23 13:21:03 +00001215static time_t
1216parse_dostime(int dostime, int dosdate)
Just van Rossum52e14d62002-12-30 22:08:05 +00001217{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001218 struct tm stm;
Just van Rossum52e14d62002-12-30 22:08:05 +00001219
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001220 memset((void *) &stm, '\0', sizeof(stm));
Christian Heimes62a8e952008-01-18 07:30:20 +00001221
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001222 stm.tm_sec = (dostime & 0x1f) * 2;
1223 stm.tm_min = (dostime >> 5) & 0x3f;
1224 stm.tm_hour = (dostime >> 11) & 0x1f;
1225 stm.tm_mday = dosdate & 0x1f;
1226 stm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;
1227 stm.tm_year = ((dosdate >> 9) & 0x7f) + 80;
1228 stm.tm_isdst = -1; /* wday/yday is ignored */
Just van Rossum52e14d62002-12-30 22:08:05 +00001229
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001230 return mktime(&stm);
Just van Rossum52e14d62002-12-30 22:08:05 +00001231}
1232
1233/* Given a path to a .pyc or .pyo file in the archive, return the
Ezio Melottic2077b02011-03-16 12:34:31 +02001234 modification time of the matching .py file, or 0 if no source
Just van Rossum52e14d62002-12-30 22:08:05 +00001235 is available. */
1236static time_t
1237get_mtime_of_source(ZipImporter *self, char *path)
1238{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001239 PyObject *toc_entry;
1240 time_t mtime = 0;
1241 Py_ssize_t lastchar = strlen(path) - 1;
1242 char savechar = path[lastchar];
1243 path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */
1244 toc_entry = PyDict_GetItemString(self->files, path);
1245 if (toc_entry != NULL && PyTuple_Check(toc_entry) &&
1246 PyTuple_Size(toc_entry) == 8) {
1247 /* fetch the time stamp of the .py file for comparison
1248 with an embedded pyc time stamp */
1249 int time, date;
1250 time = PyInt_AsLong(PyTuple_GetItem(toc_entry, 5));
1251 date = PyInt_AsLong(PyTuple_GetItem(toc_entry, 6));
1252 mtime = parse_dostime(time, date);
1253 }
1254 path[lastchar] = savechar;
1255 return mtime;
Just van Rossum52e14d62002-12-30 22:08:05 +00001256}
1257
1258/* Return the code object for the module named by 'fullname' from the
1259 Zip archive as a new reference. */
1260static PyObject *
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001261get_code_from_data(char *archive, FILE *fp, int ispackage,
1262 int isbytecode, time_t mtime, PyObject *toc_entry)
Just van Rossum52e14d62002-12-30 22:08:05 +00001263{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001264 PyObject *data, *code;
1265 char *modpath;
Just van Rossum52e14d62002-12-30 22:08:05 +00001266
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001267 data = get_data(fp, archive, toc_entry);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001268 if (data == NULL)
1269 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001270
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001271 modpath = PyString_AsString(PyTuple_GetItem(toc_entry, 0));
Just van Rossum52e14d62002-12-30 22:08:05 +00001272
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001273 if (isbytecode) {
1274 code = unmarshal_code(modpath, data, mtime);
1275 }
1276 else {
1277 code = compile_source(modpath, data);
1278 }
1279 Py_DECREF(data);
1280 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001281}
1282
Ezio Melotti24b07bc2011-03-15 18:55:01 +02001283/* Get the code object associated with the module specified by
Just van Rossum52e14d62002-12-30 22:08:05 +00001284 'fullname'. */
1285static PyObject *
1286get_module_code(ZipImporter *self, char *fullname,
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001287 int *p_ispackage, char **p_modpath)
Just van Rossum52e14d62002-12-30 22:08:05 +00001288{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001289 PyObject *toc_entry;
1290 char *subname, path[MAXPATHLEN + 1];
1291 int len;
1292 struct st_zip_searchorder *zso;
Gregory P. Smith6de72602014-01-07 18:39:48 -08001293 FILE *fp;
1294 char *archive;
Just van Rossum52e14d62002-12-30 22:08:05 +00001295
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001296 subname = get_subname(fullname);
Just van Rossum52e14d62002-12-30 22:08:05 +00001297
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001298 len = make_filename(PyString_AsString(self->prefix), subname, path);
1299 if (len < 0)
1300 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001301
Gregory P. Smith6de72602014-01-07 18:39:48 -08001302 fp = safely_reopen_archive(self, &archive);
1303 if (fp == NULL)
1304 return NULL;
1305
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001306 for (zso = zip_searchorder; *zso->suffix; zso++) {
1307 PyObject *code = NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001308
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001309 strcpy(path + len, zso->suffix);
1310 if (Py_VerboseFlag > 1)
1311 PySys_WriteStderr("# trying %s%c%s\n",
1312 PyString_AsString(self->archive),
1313 SEP, path);
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001314
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001315 toc_entry = PyDict_GetItemString(self->files, path);
1316 if (toc_entry != NULL) {
1317 time_t mtime = 0;
1318 int ispackage = zso->type & IS_PACKAGE;
1319 int isbytecode = zso->type & IS_BYTECODE;
Just van Rossum52e14d62002-12-30 22:08:05 +00001320
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001321 if (isbytecode)
1322 mtime = get_mtime_of_source(self, path);
1323 if (p_ispackage != NULL)
1324 *p_ispackage = ispackage;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001325 code = get_code_from_data(archive, fp, ispackage,
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001326 isbytecode, mtime,
1327 toc_entry);
1328 if (code == Py_None) {
1329 /* bad magic number or non-matching mtime
1330 in byte code, try next */
1331 Py_DECREF(code);
1332 continue;
1333 }
1334 if (code != NULL && p_modpath != NULL)
1335 *p_modpath = PyString_AsString(
1336 PyTuple_GetItem(toc_entry, 0));
Gregory P. Smith6de72602014-01-07 18:39:48 -08001337 fclose(fp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001338 return code;
1339 }
1340 }
1341 PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname);
Gregory P. Smith6de72602014-01-07 18:39:48 -08001342 fclose(fp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001343 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001344}
1345
1346
1347/* Module init */
1348
1349PyDoc_STRVAR(zipimport_doc,
1350"zipimport provides support for importing Python modules from Zip archives.\n\
1351\n\
1352This module exports three objects:\n\
1353- zipimporter: a class; its constructor takes a path to a Zip archive.\n\
Fredrik Lundhb84b35f2006-01-15 15:00:40 +00001354- ZipImportError: exception raised by zipimporter objects. It's a\n\
Just van Rossum52e14d62002-12-30 22:08:05 +00001355 subclass of ImportError, so it can be caught as ImportError, too.\n\
1356- _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
1357 info dicts, as used in zipimporter._files.\n\
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001358- _zip_stat_cache: a dict, mapping archive paths to stat_result\n\
1359 info for the .zip the last time anything was imported from it.\n\
Just van Rossum52e14d62002-12-30 22:08:05 +00001360\n\
1361It is usually not needed to use the zipimport module explicitly; it is\n\
1362used by the builtin import mechanism for sys.path items that are paths\n\
1363to Zip archives.");
1364
1365PyMODINIT_FUNC
1366initzipimport(void)
1367{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001368 PyObject *mod;
Just van Rossum52e14d62002-12-30 22:08:05 +00001369
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001370 if (PyType_Ready(&ZipImporter_Type) < 0)
1371 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001372
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001373 /* Correct directory separator */
1374 zip_searchorder[0].suffix[0] = SEP;
1375 zip_searchorder[1].suffix[0] = SEP;
1376 zip_searchorder[2].suffix[0] = SEP;
1377 if (Py_OptimizeFlag) {
1378 /* Reverse *.pyc and *.pyo */
1379 struct st_zip_searchorder tmp;
1380 tmp = zip_searchorder[0];
1381 zip_searchorder[0] = zip_searchorder[1];
1382 zip_searchorder[1] = tmp;
1383 tmp = zip_searchorder[3];
1384 zip_searchorder[3] = zip_searchorder[4];
1385 zip_searchorder[4] = tmp;
1386 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001387
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001388 mod = Py_InitModule4("zipimport", NULL, zipimport_doc,
1389 NULL, PYTHON_API_VERSION);
1390 if (mod == NULL)
1391 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001392
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001393 ZipImportError = PyErr_NewException("zipimport.ZipImportError",
1394 PyExc_ImportError, NULL);
1395 if (ZipImportError == NULL)
1396 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001397
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001398 Py_INCREF(ZipImportError);
1399 if (PyModule_AddObject(mod, "ZipImportError",
1400 ZipImportError) < 0)
1401 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001402
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001403 Py_INCREF(&ZipImporter_Type);
1404 if (PyModule_AddObject(mod, "zipimporter",
1405 (PyObject *)&ZipImporter_Type) < 0)
1406 return;
Just van Rossumf8b6de12002-12-31 09:51:59 +00001407
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001408 Py_XDECREF(zip_directory_cache); /* Avoid embedded interpreter leaks. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001409 zip_directory_cache = PyDict_New();
1410 if (zip_directory_cache == NULL)
1411 return;
1412 Py_INCREF(zip_directory_cache);
1413 if (PyModule_AddObject(mod, "_zip_directory_cache",
1414 zip_directory_cache) < 0)
1415 return;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001416
1417 Py_XDECREF(zip_stat_cache); /* Avoid embedded interpreter leaks. */
1418 zip_stat_cache = PyDict_New();
1419 if (zip_stat_cache == NULL)
1420 return;
1421 Py_INCREF(zip_stat_cache);
1422 if (PyModule_AddObject(mod, "_zip_stat_cache", zip_stat_cache) < 0)
1423 return;
1424
1425 {
1426 /* We cannot import "os" here as that is a .py/.pyc file that could
1427 * live within a zipped up standard library. Import the posix or nt
1428 * builtin that provides the fstat() function we want instead. */
1429 PyObject *os_like_module;
Gregory P. Smithad3e7252014-01-07 01:11:09 -08001430 Py_CLEAR(fstat_function); /* Avoid embedded interpreter leaks. */
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001431 os_like_module = PyImport_ImportModule("posix");
1432 if (os_like_module == NULL) {
Gregory P. Smithad3e7252014-01-07 01:11:09 -08001433 PyErr_Clear();
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001434 os_like_module = PyImport_ImportModule("nt");
1435 }
1436 if (os_like_module != NULL) {
1437 fstat_function = PyObject_GetAttrString(os_like_module, "fstat");
1438 Py_DECREF(os_like_module);
1439 }
1440 if (fstat_function == NULL) {
1441 PyErr_Clear(); /* non-fatal, we'll go on without it. */
Gregory P. Smithad3e7252014-01-07 01:11:09 -08001442 if (Py_VerboseFlag)
1443 PySys_WriteStderr("# zipimport unable to use os.fstat().\n");
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001444 }
1445 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001446}