blob: bbfbda956f60294ba7f05c7a97852f35529f1377 [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;
835 } else {
836 /* No problem, discard the new stat data. */
837 Py_DECREF(stat_now);
838 }
839 } /* stat succeeded */
840
841 return fp;
842}
843
844/*
845 read_directory(fp, archive) -> files dict (new reference)
Just van Rossum52e14d62002-12-30 22:08:05 +0000846
847 Given a path to a Zip archive, build a dict, mapping file names
848 (local to the archive, using SEP as a separator) to toc entries.
849
850 A toc_entry is a tuple:
851
Fred Drakef5b7fd22005-11-11 19:34:56 +0000852 (__file__, # value to use for __file__, available for all files
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000853 compress, # compression kind; 0 for uncompressed
854 data_size, # size of compressed data on disk
855 file_size, # size of decompressed data
856 file_offset, # offset of file header from start of archive
857 time, # mod time of file (in dos format)
858 date, # mod data of file (in dos format)
859 crc, # crc checksum of the data
Just van Rossum52e14d62002-12-30 22:08:05 +0000860 )
861
862 Directories can be recognized by the trailing SEP in the name,
863 data_size and file_offset are 0.
864*/
865static PyObject *
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800866read_directory(FILE *fp, char *archive)
Just van Rossum52e14d62002-12-30 22:08:05 +0000867{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000868 PyObject *files = NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000869 long compress, crc, data_size, file_size, file_offset, date, time;
870 long header_offset, name_size, header_size, header_position;
871 long i, l, count;
872 size_t length;
873 char path[MAXPATHLEN + 5];
874 char name[MAXPATHLEN + 5];
875 char *p, endof_central_dir[22];
876 long arc_offset; /* offset from beginning of file to start of zip-archive */
Just van Rossum52e14d62002-12-30 22:08:05 +0000877
Gregory P. Smithb48c5d52014-01-06 09:46:46 -0800878 assert(fp != NULL);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000879 if (strlen(archive) > MAXPATHLEN) {
880 PyErr_SetString(PyExc_OverflowError,
881 "Zip path name is too long");
882 return NULL;
883 }
884 strcpy(path, archive);
Just van Rossum52e14d62002-12-30 22:08:05 +0000885
Jesus Ceae884be62012-10-03 02:13:05 +0200886 if (fseek(fp, -22, SEEK_END) == -1) {
Jesus Ceae884be62012-10-03 02:13:05 +0200887 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
888 return NULL;
889 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000890 header_position = ftell(fp);
891 if (fread(endof_central_dir, 1, 22, fp) != 22) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000892 PyErr_Format(ZipImportError, "can't read Zip file: "
893 "'%.200s'", archive);
894 return NULL;
895 }
896 if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
897 /* Bad: End of Central Dir signature */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000898 PyErr_Format(ZipImportError, "not a Zip file: "
899 "'%.200s'", archive);
900 return NULL;
901 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000902
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000903 header_size = get_long((unsigned char *)endof_central_dir + 12);
904 header_offset = get_long((unsigned char *)endof_central_dir + 16);
905 arc_offset = header_position - header_offset - header_size;
906 header_offset += arc_offset;
Just van Rossum52e14d62002-12-30 22:08:05 +0000907
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000908 files = PyDict_New();
909 if (files == NULL)
910 goto error;
Just van Rossum52e14d62002-12-30 22:08:05 +0000911
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000912 length = (long)strlen(path);
913 path[length] = SEP;
Just van Rossum52e14d62002-12-30 22:08:05 +0000914
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000915 /* Start of Central Directory */
916 count = 0;
917 for (;;) {
918 PyObject *t;
919 int err;
Just van Rossum52e14d62002-12-30 22:08:05 +0000920
Jesus Ceae884be62012-10-03 02:13:05 +0200921 if (fseek(fp, header_offset, 0) == -1) /* Start of file header */
922 goto fseek_error;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000923 l = PyMarshal_ReadLongFromFile(fp);
924 if (l != 0x02014B50)
925 break; /* Bad: Central Dir File Header */
Jesus Ceae884be62012-10-03 02:13:05 +0200926 if (fseek(fp, header_offset + 10, 0) == -1)
927 goto fseek_error;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000928 compress = PyMarshal_ReadShortFromFile(fp);
929 time = PyMarshal_ReadShortFromFile(fp);
930 date = PyMarshal_ReadShortFromFile(fp);
931 crc = PyMarshal_ReadLongFromFile(fp);
932 data_size = PyMarshal_ReadLongFromFile(fp);
933 file_size = PyMarshal_ReadLongFromFile(fp);
934 name_size = PyMarshal_ReadShortFromFile(fp);
935 header_size = 46 + name_size +
936 PyMarshal_ReadShortFromFile(fp) +
937 PyMarshal_ReadShortFromFile(fp);
Jesus Ceae884be62012-10-03 02:13:05 +0200938 if (fseek(fp, header_offset + 42, 0) == -1)
939 goto fseek_error;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000940 file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
941 if (name_size > MAXPATHLEN)
942 name_size = MAXPATHLEN;
Just van Rossum52e14d62002-12-30 22:08:05 +0000943
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000944 p = name;
945 for (i = 0; i < name_size; i++) {
946 *p = (char)getc(fp);
947 if (*p == '/')
948 *p = SEP;
949 p++;
950 }
951 *p = 0; /* Add terminating null byte */
952 header_offset += header_size;
Just van Rossum52e14d62002-12-30 22:08:05 +0000953
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000954 strncpy(path + length + 1, name, MAXPATHLEN - length - 1);
Just van Rossum52e14d62002-12-30 22:08:05 +0000955
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000956 t = Py_BuildValue("siiiiiii", path, compress, data_size,
957 file_size, file_offset, time, date, crc);
958 if (t == NULL)
959 goto error;
960 err = PyDict_SetItemString(files, name, t);
961 Py_DECREF(t);
962 if (err != 0)
963 goto error;
964 count++;
965 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000966 if (Py_VerboseFlag)
967 PySys_WriteStderr("# zipimport: found %ld names in %s\n",
968 count, archive);
969 return files;
Jesus Ceae884be62012-10-03 02:13:05 +0200970fseek_error:
Jesus Ceae884be62012-10-03 02:13:05 +0200971 Py_XDECREF(files);
972 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
973 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000974error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000975 Py_XDECREF(files);
976 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +0000977}
978
979/* Return the zlib.decompress function object, or NULL if zlib couldn't
980 be imported. The function is cached when found, so subsequent calls
Victor Stinnerf58f1c32011-05-21 02:13:22 +0200981 don't import zlib again. */
Just van Rossum52e14d62002-12-30 22:08:05 +0000982static PyObject *
983get_decompress_func(void)
984{
Victor Stinnerf58f1c32011-05-21 02:13:22 +0200985 static int importing_zlib = 0;
986 PyObject *zlib;
987 PyObject *decompress;
Just van Rossum52e14d62002-12-30 22:08:05 +0000988
Victor Stinnerf58f1c32011-05-21 02:13:22 +0200989 if (importing_zlib != 0)
990 /* Someone has a zlib.py[co] in their Zip file;
991 let's avoid a stack overflow. */
992 return NULL;
993 importing_zlib = 1;
994 zlib = PyImport_ImportModuleNoBlock("zlib");
995 importing_zlib = 0;
996 if (zlib != NULL) {
997 decompress = PyObject_GetAttrString(zlib,
998 "decompress");
999 Py_DECREF(zlib);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001000 }
Victor Stinnerf58f1c32011-05-21 02:13:22 +02001001 else {
1002 PyErr_Clear();
1003 decompress = NULL;
1004 }
1005 if (Py_VerboseFlag)
1006 PySys_WriteStderr("# zipimport: zlib %s\n",
1007 zlib != NULL ? "available": "UNAVAILABLE");
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001008 return decompress;
Just van Rossum52e14d62002-12-30 22:08:05 +00001009}
1010
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001011/* Given a FILE* to a Zip file and a toc_entry, return the (uncompressed)
Just van Rossum52e14d62002-12-30 22:08:05 +00001012 data as a new reference. */
1013static PyObject *
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001014get_data(FILE *fp, char *archive, PyObject *toc_entry)
Just van Rossum52e14d62002-12-30 22:08:05 +00001015{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001016 PyObject *raw_data, *data = NULL, *decompress;
1017 char *buf;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001018 int err;
1019 Py_ssize_t bytes_read = 0;
1020 long l;
1021 char *datapath;
1022 long compress, data_size, file_size, file_offset;
1023 long time, date, crc;
Just van Rossum52e14d62002-12-30 22:08:05 +00001024
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001025 if (!PyArg_ParseTuple(toc_entry, "slllllll", &datapath, &compress,
1026 &data_size, &file_size, &file_offset, &time,
1027 &date, &crc)) {
1028 return NULL;
1029 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001030
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001031 /* Check to make sure the local file header is correct */
Jesus Ceae884be62012-10-03 02:13:05 +02001032 if (fseek(fp, file_offset, 0) == -1) {
Jesus Ceae884be62012-10-03 02:13:05 +02001033 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
1034 return NULL;
1035 }
1036
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001037 l = PyMarshal_ReadLongFromFile(fp);
1038 if (l != 0x04034B50) {
1039 /* Bad: Local File Header */
1040 PyErr_Format(ZipImportError,
1041 "bad local file header in %s",
1042 archive);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001043 return NULL;
1044 }
Jesus Ceae884be62012-10-03 02:13:05 +02001045 if (fseek(fp, file_offset + 26, 0) == -1) {
Jesus Ceae884be62012-10-03 02:13:05 +02001046 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
1047 return NULL;
1048 }
1049
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001050 l = 30 + PyMarshal_ReadShortFromFile(fp) +
1051 PyMarshal_ReadShortFromFile(fp); /* local header size */
1052 file_offset += l; /* Start of file data */
Just van Rossum52e14d62002-12-30 22:08:05 +00001053
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001054 raw_data = PyString_FromStringAndSize((char *)NULL, compress == 0 ?
1055 data_size : data_size + 1);
1056 if (raw_data == NULL) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001057 return NULL;
1058 }
1059 buf = PyString_AsString(raw_data);
Just van Rossum52e14d62002-12-30 22:08:05 +00001060
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001061 err = fseek(fp, file_offset, 0);
Jesus Ceae884be62012-10-03 02:13:05 +02001062 if (err == 0) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001063 bytes_read = fread(buf, 1, data_size, fp);
Jesus Ceae884be62012-10-03 02:13:05 +02001064 } else {
Jesus Ceae884be62012-10-03 02:13:05 +02001065 PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);
1066 return NULL;
1067 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001068 if (err || bytes_read != data_size) {
1069 PyErr_SetString(PyExc_IOError,
1070 "zipimport: can't read data");
1071 Py_DECREF(raw_data);
1072 return NULL;
1073 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001074
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001075 if (compress != 0) {
1076 buf[data_size] = 'Z'; /* saw this in zipfile.py */
1077 data_size++;
1078 }
1079 buf[data_size] = '\0';
Just van Rossum52e14d62002-12-30 22:08:05 +00001080
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001081 if (compress == 0) /* data is not compressed */
1082 return raw_data;
Just van Rossum52e14d62002-12-30 22:08:05 +00001083
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001084 /* Decompress with zlib */
1085 decompress = get_decompress_func();
1086 if (decompress == NULL) {
1087 PyErr_SetString(ZipImportError,
1088 "can't decompress data; "
1089 "zlib not available");
1090 goto error;
1091 }
1092 data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
Victor Stinnerf58f1c32011-05-21 02:13:22 +02001093 Py_DECREF(decompress);
Just van Rossum52e14d62002-12-30 22:08:05 +00001094error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001095 Py_DECREF(raw_data);
1096 return data;
Just van Rossum52e14d62002-12-30 22:08:05 +00001097}
1098
1099/* Lenient date/time comparison function. The precision of the mtime
1100 in the archive is lower than the mtime stored in a .pyc: we
1101 must allow a difference of at most one second. */
1102static int
1103eq_mtime(time_t t1, time_t t2)
1104{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001105 time_t d = t1 - t2;
1106 if (d < 0)
1107 d = -d;
1108 /* dostime only stores even seconds, so be lenient */
1109 return d <= 1;
Just van Rossum52e14d62002-12-30 22:08:05 +00001110}
1111
1112/* Given the contents of a .py[co] file in a buffer, unmarshal the data
1113 and return the code object. Return None if it the magic word doesn't
1114 match (we do this instead of raising an exception as we fall back
1115 to .py if available and we don't want to mask other errors).
1116 Returns a new reference. */
1117static PyObject *
1118unmarshal_code(char *pathname, PyObject *data, time_t mtime)
1119{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001120 PyObject *code;
1121 char *buf = PyString_AsString(data);
1122 Py_ssize_t size = PyString_Size(data);
Just van Rossum52e14d62002-12-30 22:08:05 +00001123
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001124 if (size <= 9) {
1125 PyErr_SetString(ZipImportError,
1126 "bad pyc data");
1127 return NULL;
1128 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001129
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001130 if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {
1131 if (Py_VerboseFlag)
1132 PySys_WriteStderr("# %s has bad magic\n",
1133 pathname);
1134 Py_INCREF(Py_None);
1135 return Py_None; /* signal caller to try alternative */
1136 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001137
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001138 if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),
1139 mtime)) {
1140 if (Py_VerboseFlag)
1141 PySys_WriteStderr("# %s has bad mtime\n",
1142 pathname);
1143 Py_INCREF(Py_None);
1144 return Py_None; /* signal caller to try alternative */
1145 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001146
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001147 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
1148 if (code == NULL)
1149 return NULL;
1150 if (!PyCode_Check(code)) {
1151 Py_DECREF(code);
1152 PyErr_Format(PyExc_TypeError,
1153 "compiled module %.200s is not a code object",
1154 pathname);
1155 return NULL;
1156 }
1157 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001158}
1159
1160/* Replace any occurances of "\r\n?" in the input string with "\n".
1161 This converts DOS and Mac line endings to Unix line endings.
1162 Also append a trailing "\n" to be compatible with
1163 PyParser_SimpleParseFile(). Returns a new reference. */
1164static PyObject *
1165normalize_line_endings(PyObject *source)
1166{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001167 char *buf, *q, *p = PyString_AsString(source);
1168 PyObject *fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001169
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001170 if (!p)
1171 return NULL;
Neal Norwitzee7c8f92006-08-13 18:12:03 +00001172
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001173 /* one char extra for trailing \n and one for terminating \0 */
1174 buf = (char *)PyMem_Malloc(PyString_Size(source) + 2);
1175 if (buf == NULL) {
1176 PyErr_SetString(PyExc_MemoryError,
1177 "zipimport: no memory to allocate "
1178 "source buffer");
1179 return NULL;
1180 }
1181 /* replace "\r\n?" by "\n" */
1182 for (q = buf; *p != '\0'; p++) {
1183 if (*p == '\r') {
1184 *q++ = '\n';
1185 if (*(p + 1) == '\n')
1186 p++;
1187 }
1188 else
1189 *q++ = *p;
1190 }
1191 *q++ = '\n'; /* add trailing \n */
1192 *q = '\0';
1193 fixed_source = PyString_FromString(buf);
1194 PyMem_Free(buf);
1195 return fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001196}
1197
1198/* Given a string buffer containing Python source code, compile it
1199 return and return a code object as a new reference. */
1200static PyObject *
1201compile_source(char *pathname, PyObject *source)
1202{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001203 PyObject *code, *fixed_source;
Just van Rossum52e14d62002-12-30 22:08:05 +00001204
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001205 fixed_source = normalize_line_endings(source);
1206 if (fixed_source == NULL)
1207 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001208
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001209 code = Py_CompileString(PyString_AsString(fixed_source), pathname,
1210 Py_file_input);
1211 Py_DECREF(fixed_source);
1212 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001213}
1214
1215/* Convert the date/time values found in the Zip archive to a value
1216 that's compatible with the time stamp stored in .pyc files. */
Neal Norwitz29fd2ba2003-03-23 13:21:03 +00001217static time_t
1218parse_dostime(int dostime, int dosdate)
Just van Rossum52e14d62002-12-30 22:08:05 +00001219{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001220 struct tm stm;
Just van Rossum52e14d62002-12-30 22:08:05 +00001221
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001222 memset((void *) &stm, '\0', sizeof(stm));
Christian Heimes62a8e952008-01-18 07:30:20 +00001223
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001224 stm.tm_sec = (dostime & 0x1f) * 2;
1225 stm.tm_min = (dostime >> 5) & 0x3f;
1226 stm.tm_hour = (dostime >> 11) & 0x1f;
1227 stm.tm_mday = dosdate & 0x1f;
1228 stm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;
1229 stm.tm_year = ((dosdate >> 9) & 0x7f) + 80;
1230 stm.tm_isdst = -1; /* wday/yday is ignored */
Just van Rossum52e14d62002-12-30 22:08:05 +00001231
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001232 return mktime(&stm);
Just van Rossum52e14d62002-12-30 22:08:05 +00001233}
1234
1235/* Given a path to a .pyc or .pyo file in the archive, return the
Ezio Melottic2077b02011-03-16 12:34:31 +02001236 modification time of the matching .py file, or 0 if no source
Just van Rossum52e14d62002-12-30 22:08:05 +00001237 is available. */
1238static time_t
1239get_mtime_of_source(ZipImporter *self, char *path)
1240{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001241 PyObject *toc_entry;
1242 time_t mtime = 0;
1243 Py_ssize_t lastchar = strlen(path) - 1;
1244 char savechar = path[lastchar];
1245 path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */
1246 toc_entry = PyDict_GetItemString(self->files, path);
1247 if (toc_entry != NULL && PyTuple_Check(toc_entry) &&
1248 PyTuple_Size(toc_entry) == 8) {
1249 /* fetch the time stamp of the .py file for comparison
1250 with an embedded pyc time stamp */
1251 int time, date;
1252 time = PyInt_AsLong(PyTuple_GetItem(toc_entry, 5));
1253 date = PyInt_AsLong(PyTuple_GetItem(toc_entry, 6));
1254 mtime = parse_dostime(time, date);
1255 }
1256 path[lastchar] = savechar;
1257 return mtime;
Just van Rossum52e14d62002-12-30 22:08:05 +00001258}
1259
1260/* Return the code object for the module named by 'fullname' from the
1261 Zip archive as a new reference. */
1262static PyObject *
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001263get_code_from_data(char *archive, FILE *fp, int ispackage,
1264 int isbytecode, time_t mtime, PyObject *toc_entry)
Just van Rossum52e14d62002-12-30 22:08:05 +00001265{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001266 PyObject *data, *code;
1267 char *modpath;
Just van Rossum52e14d62002-12-30 22:08:05 +00001268
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001269 data = get_data(fp, archive, toc_entry);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001270 if (data == NULL)
1271 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001272
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001273 modpath = PyString_AsString(PyTuple_GetItem(toc_entry, 0));
Just van Rossum52e14d62002-12-30 22:08:05 +00001274
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001275 if (isbytecode) {
1276 code = unmarshal_code(modpath, data, mtime);
1277 }
1278 else {
1279 code = compile_source(modpath, data);
1280 }
1281 Py_DECREF(data);
1282 return code;
Just van Rossum52e14d62002-12-30 22:08:05 +00001283}
1284
Ezio Melotti24b07bc2011-03-15 18:55:01 +02001285/* Get the code object associated with the module specified by
Just van Rossum52e14d62002-12-30 22:08:05 +00001286 'fullname'. */
1287static PyObject *
1288get_module_code(ZipImporter *self, char *fullname,
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001289 int *p_ispackage, char **p_modpath)
Just van Rossum52e14d62002-12-30 22:08:05 +00001290{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001291 PyObject *toc_entry;
1292 char *subname, path[MAXPATHLEN + 1];
1293 int len;
1294 struct st_zip_searchorder *zso;
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
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001302 for (zso = zip_searchorder; *zso->suffix; zso++) {
1303 PyObject *code = NULL;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001304 FILE *fp;
1305 char *archive;
Just van Rossum52e14d62002-12-30 22:08:05 +00001306
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001307 strcpy(path + len, zso->suffix);
1308 if (Py_VerboseFlag > 1)
1309 PySys_WriteStderr("# trying %s%c%s\n",
1310 PyString_AsString(self->archive),
1311 SEP, path);
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001312
1313 fp = safely_reopen_archive(self, &archive);
1314 if (fp == NULL)
1315 return NULL;
1316
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001317 toc_entry = PyDict_GetItemString(self->files, path);
1318 if (toc_entry != NULL) {
1319 time_t mtime = 0;
1320 int ispackage = zso->type & IS_PACKAGE;
1321 int isbytecode = zso->type & IS_BYTECODE;
Just van Rossum52e14d62002-12-30 22:08:05 +00001322
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001323 if (isbytecode)
1324 mtime = get_mtime_of_source(self, path);
1325 if (p_ispackage != NULL)
1326 *p_ispackage = ispackage;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001327 code = get_code_from_data(archive, fp, ispackage,
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001328 isbytecode, mtime,
1329 toc_entry);
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001330 fclose(fp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001331 if (code == Py_None) {
1332 /* bad magic number or non-matching mtime
1333 in byte code, try next */
1334 Py_DECREF(code);
1335 continue;
1336 }
1337 if (code != NULL && p_modpath != NULL)
1338 *p_modpath = PyString_AsString(
1339 PyTuple_GetItem(toc_entry, 0));
1340 return code;
1341 }
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001342 fclose(fp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001343 }
1344 PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname);
1345 return NULL;
Just van Rossum52e14d62002-12-30 22:08:05 +00001346}
1347
1348
1349/* Module init */
1350
1351PyDoc_STRVAR(zipimport_doc,
1352"zipimport provides support for importing Python modules from Zip archives.\n\
1353\n\
1354This module exports three objects:\n\
1355- zipimporter: a class; its constructor takes a path to a Zip archive.\n\
Fredrik Lundhb84b35f2006-01-15 15:00:40 +00001356- ZipImportError: exception raised by zipimporter objects. It's a\n\
Just van Rossum52e14d62002-12-30 22:08:05 +00001357 subclass of ImportError, so it can be caught as ImportError, too.\n\
1358- _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
1359 info dicts, as used in zipimporter._files.\n\
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001360- _zip_stat_cache: a dict, mapping archive paths to stat_result\n\
1361 info for the .zip the last time anything was imported from it.\n\
Just van Rossum52e14d62002-12-30 22:08:05 +00001362\n\
1363It is usually not needed to use the zipimport module explicitly; it is\n\
1364used by the builtin import mechanism for sys.path items that are paths\n\
1365to Zip archives.");
1366
1367PyMODINIT_FUNC
1368initzipimport(void)
1369{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001370 PyObject *mod;
Just van Rossum52e14d62002-12-30 22:08:05 +00001371
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001372 if (PyType_Ready(&ZipImporter_Type) < 0)
1373 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001374
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001375 /* Correct directory separator */
1376 zip_searchorder[0].suffix[0] = SEP;
1377 zip_searchorder[1].suffix[0] = SEP;
1378 zip_searchorder[2].suffix[0] = SEP;
1379 if (Py_OptimizeFlag) {
1380 /* Reverse *.pyc and *.pyo */
1381 struct st_zip_searchorder tmp;
1382 tmp = zip_searchorder[0];
1383 zip_searchorder[0] = zip_searchorder[1];
1384 zip_searchorder[1] = tmp;
1385 tmp = zip_searchorder[3];
1386 zip_searchorder[3] = zip_searchorder[4];
1387 zip_searchorder[4] = tmp;
1388 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001389
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001390 mod = Py_InitModule4("zipimport", NULL, zipimport_doc,
1391 NULL, PYTHON_API_VERSION);
1392 if (mod == NULL)
1393 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001394
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001395 ZipImportError = PyErr_NewException("zipimport.ZipImportError",
1396 PyExc_ImportError, NULL);
1397 if (ZipImportError == NULL)
1398 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001399
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001400 Py_INCREF(ZipImportError);
1401 if (PyModule_AddObject(mod, "ZipImportError",
1402 ZipImportError) < 0)
1403 return;
Just van Rossum52e14d62002-12-30 22:08:05 +00001404
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001405 Py_INCREF(&ZipImporter_Type);
1406 if (PyModule_AddObject(mod, "zipimporter",
1407 (PyObject *)&ZipImporter_Type) < 0)
1408 return;
Just van Rossumf8b6de12002-12-31 09:51:59 +00001409
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001410 Py_XDECREF(zip_directory_cache); /* Avoid embedded interpreter leaks. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001411 zip_directory_cache = PyDict_New();
1412 if (zip_directory_cache == NULL)
1413 return;
1414 Py_INCREF(zip_directory_cache);
1415 if (PyModule_AddObject(mod, "_zip_directory_cache",
1416 zip_directory_cache) < 0)
1417 return;
Gregory P. Smithb48c5d52014-01-06 09:46:46 -08001418
1419 Py_XDECREF(zip_stat_cache); /* Avoid embedded interpreter leaks. */
1420 zip_stat_cache = PyDict_New();
1421 if (zip_stat_cache == NULL)
1422 return;
1423 Py_INCREF(zip_stat_cache);
1424 if (PyModule_AddObject(mod, "_zip_stat_cache", zip_stat_cache) < 0)
1425 return;
1426
1427 {
1428 /* We cannot import "os" here as that is a .py/.pyc file that could
1429 * live within a zipped up standard library. Import the posix or nt
1430 * builtin that provides the fstat() function we want instead. */
1431 PyObject *os_like_module;
1432 Py_XDECREF(fstat_function); /* Avoid embedded interpreter leaks. */
1433 os_like_module = PyImport_ImportModule("posix");
1434 if (os_like_module == NULL) {
1435 os_like_module = PyImport_ImportModule("nt");
1436 }
1437 if (os_like_module != NULL) {
1438 fstat_function = PyObject_GetAttrString(os_like_module, "fstat");
1439 Py_DECREF(os_like_module);
1440 }
1441 if (fstat_function == NULL) {
1442 PyErr_Clear(); /* non-fatal, we'll go on without it. */
1443 }
1444 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001445}