Saved and restored logging._handlerList at the same time as saving/restoring logging...
[python.git] / Modules / zipimport.c
blob937b0f733a9f566f01c33e3eb1af84decf4878b0
1 #include "Python.h"
2 #include "structmember.h"
3 #include "osdefs.h"
4 #include "marshal.h"
5 #include <time.h>
8 #define IS_SOURCE 0x0
9 #define IS_BYTECODE 0x1
10 #define IS_PACKAGE 0x2
12 struct st_zip_searchorder {
13 char suffix[14];
14 int type;
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. */
22 static struct st_zip_searchorder zip_searchorder[] = {
23 {"/__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}
32 /* zipimporter object definition and support */
34 typedef struct _zipimporter ZipImporter;
36 struct _zipimporter {
37 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} */
43 static PyTypeObject ZipImporter_Type;
44 static PyObject *ZipImportError;
45 static PyObject *zip_directory_cache = NULL;
47 /* forward decls */
48 static PyObject *read_directory(char *archive);
49 static PyObject *get_data(char *archive, PyObject *toc_entry);
50 static PyObject *get_module_code(ZipImporter *self, char *fullname,
51 int *p_ispackage, char **p_modpath);
54 #define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type)
57 /* zipimporter.__init__
58 Split the "subdirectory" from the Zip archive path, lookup a matching
59 entry in sys.path_importer_cache, fetch the file directory from there
60 if found, or else read it from the archive. */
61 static int
62 zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
64 char *path, *p, *prefix, buf[MAXPATHLEN+2];
65 size_t len;
67 if (!_PyArg_NoKeywords("zipimporter()", kwds))
68 return -1;
70 if (!PyArg_ParseTuple(args, "s:zipimporter",
71 &path))
72 return -1;
74 len = strlen(path);
75 if (len == 0) {
76 PyErr_SetString(ZipImportError, "archive path is empty");
77 return -1;
79 if (len >= MAXPATHLEN) {
80 PyErr_SetString(ZipImportError,
81 "archive path too long");
82 return -1;
84 strcpy(buf, path);
86 #ifdef ALTSEP
87 for (p = buf; *p; p++) {
88 if (*p == ALTSEP)
89 *p = SEP;
91 #endif
93 path = NULL;
94 prefix = NULL;
95 for (;;) {
96 #ifndef RISCOS
97 struct stat statbuf;
98 int rv;
100 rv = stat(buf, &statbuf);
101 if (rv == 0) {
102 /* it exists */
103 if (S_ISREG(statbuf.st_mode))
104 /* it's a file */
105 path = buf;
106 break;
108 #else
109 if (object_exists(buf)) {
110 /* it exists */
111 if (isfile(buf))
112 /* it's a file */
113 path = buf;
114 break;
116 #endif
117 /* back up one path element */
118 p = strrchr(buf, SEP);
119 if (prefix != NULL)
120 *prefix = SEP;
121 if (p == NULL)
122 break;
123 *p = '\0';
124 prefix = p;
126 if (path != NULL) {
127 PyObject *files;
128 files = PyDict_GetItemString(zip_directory_cache, path);
129 if (files == NULL) {
130 files = read_directory(buf);
131 if (files == NULL)
132 return -1;
133 if (PyDict_SetItemString(zip_directory_cache, path,
134 files) != 0)
135 return -1;
137 else
138 Py_INCREF(files);
139 self->files = files;
141 else {
142 PyErr_SetString(ZipImportError, "not a Zip file");
143 return -1;
146 if (prefix == NULL)
147 prefix = "";
148 else {
149 prefix++;
150 len = strlen(prefix);
151 if (prefix[len-1] != SEP) {
152 /* add trailing SEP */
153 prefix[len] = SEP;
154 prefix[len + 1] = '\0';
158 self->archive = PyString_FromString(buf);
159 if (self->archive == NULL)
160 return -1;
162 self->prefix = PyString_FromString(prefix);
163 if (self->prefix == NULL)
164 return -1;
166 return 0;
169 /* GC support. */
170 static int
171 zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
173 ZipImporter *self = (ZipImporter *)obj;
174 int err;
176 if (self->files != NULL) {
177 err = visit(self->files, arg);
178 if (err)
179 return err;
181 return 0;
184 static void
185 zipimporter_dealloc(ZipImporter *self)
187 PyObject_GC_UnTrack(self);
188 Py_XDECREF(self->archive);
189 Py_XDECREF(self->prefix);
190 Py_XDECREF(self->files);
191 self->ob_type->tp_free((PyObject *)self);
194 static PyObject *
195 zipimporter_repr(ZipImporter *self)
197 char buf[500];
198 char *archive = "???";
199 char *prefix = "";
201 if (self->archive != NULL && PyString_Check(self->archive))
202 archive = PyString_AsString(self->archive);
203 if (self->prefix != NULL && PyString_Check(self->prefix))
204 prefix = PyString_AsString(self->prefix);
205 if (prefix != NULL && *prefix)
206 PyOS_snprintf(buf, sizeof(buf),
207 "<zipimporter object \"%.300s%c%.150s\">",
208 archive, SEP, prefix);
209 else
210 PyOS_snprintf(buf, sizeof(buf),
211 "<zipimporter object \"%.300s\">",
212 archive);
213 return PyString_FromString(buf);
216 /* return fullname.split(".")[-1] */
217 static char *
218 get_subname(char *fullname)
220 char *subname = strrchr(fullname, '.');
221 if (subname == NULL)
222 subname = fullname;
223 else
224 subname++;
225 return subname;
228 /* Given a (sub)modulename, write the potential file path in the
229 archive (without extension) to the path buffer. Return the
230 length of the resulting string. */
231 static int
232 make_filename(char *prefix, char *name, char *path)
234 size_t len;
235 char *p;
237 len = strlen(prefix);
239 /* self.prefix + name [+ SEP + "__init__"] + ".py[co]" */
240 if (len + strlen(name) + 13 >= MAXPATHLEN) {
241 PyErr_SetString(ZipImportError, "path too long");
242 return -1;
245 strcpy(path, prefix);
246 strcpy(path + len, name);
247 for (p = path + len; *p; p++) {
248 if (*p == '.')
249 *p = SEP;
251 len += strlen(name);
252 return (int)len;
255 enum zi_module_info {
256 MI_ERROR,
257 MI_NOT_FOUND,
258 MI_MODULE,
259 MI_PACKAGE
262 /* Return some information about a module. */
263 static enum zi_module_info
264 get_module_info(ZipImporter *self, char *fullname)
266 char *subname, path[MAXPATHLEN + 1];
267 int len;
268 struct st_zip_searchorder *zso;
270 subname = get_subname(fullname);
272 len = make_filename(PyString_AsString(self->prefix), subname, path);
273 if (len < 0)
274 return MI_ERROR;
276 for (zso = zip_searchorder; *zso->suffix; zso++) {
277 strcpy(path + len, zso->suffix);
278 if (PyDict_GetItemString(self->files, path) != NULL) {
279 if (zso->type & IS_PACKAGE)
280 return MI_PACKAGE;
281 else
282 return MI_MODULE;
285 return MI_NOT_FOUND;
288 /* Check whether we can satisfy the import of the module named by
289 'fullname'. Return self if we can, None if we can't. */
290 static PyObject *
291 zipimporter_find_module(PyObject *obj, PyObject *args)
293 ZipImporter *self = (ZipImporter *)obj;
294 PyObject *path = NULL;
295 char *fullname;
296 enum zi_module_info mi;
298 if (!PyArg_ParseTuple(args, "s|O:zipimporter.find_module",
299 &fullname, &path))
300 return NULL;
302 mi = get_module_info(self, fullname);
303 if (mi == MI_ERROR)
304 return NULL;
305 if (mi == MI_NOT_FOUND) {
306 Py_INCREF(Py_None);
307 return Py_None;
309 Py_INCREF(self);
310 return (PyObject *)self;
313 /* Load and return the module named by 'fullname'. */
314 static PyObject *
315 zipimporter_load_module(PyObject *obj, PyObject *args)
317 ZipImporter *self = (ZipImporter *)obj;
318 PyObject *code, *mod, *dict;
319 char *fullname, *modpath;
320 int ispackage;
322 if (!PyArg_ParseTuple(args, "s:zipimporter.load_module",
323 &fullname))
324 return NULL;
326 code = get_module_code(self, fullname, &ispackage, &modpath);
327 if (code == NULL)
328 return NULL;
330 mod = PyImport_AddModule(fullname);
331 if (mod == NULL) {
332 Py_DECREF(code);
333 return NULL;
335 dict = PyModule_GetDict(mod);
337 /* mod.__loader__ = self */
338 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
339 goto error;
341 if (ispackage) {
342 /* add __path__ to the module *before* the code gets
343 executed */
344 PyObject *pkgpath, *fullpath;
345 char *prefix = PyString_AsString(self->prefix);
346 char *subname = get_subname(fullname);
347 int err;
349 fullpath = PyString_FromFormat("%s%c%s%s",
350 PyString_AsString(self->archive),
351 SEP,
352 *prefix ? prefix : "",
353 subname);
354 if (fullpath == NULL)
355 goto error;
357 pkgpath = Py_BuildValue("[O]", fullpath);
358 Py_DECREF(fullpath);
359 if (pkgpath == NULL)
360 goto error;
361 err = PyDict_SetItemString(dict, "__path__", pkgpath);
362 Py_DECREF(pkgpath);
363 if (err != 0)
364 goto error;
366 mod = PyImport_ExecCodeModuleEx(fullname, code, modpath);
367 Py_DECREF(code);
368 if (Py_VerboseFlag)
369 PySys_WriteStderr("import %s # loaded from Zip %s\n",
370 fullname, modpath);
371 return mod;
372 error:
373 Py_DECREF(code);
374 Py_DECREF(mod);
375 return NULL;
378 /* Return a bool signifying whether the module is a package or not. */
379 static PyObject *
380 zipimporter_is_package(PyObject *obj, PyObject *args)
382 ZipImporter *self = (ZipImporter *)obj;
383 char *fullname;
384 enum zi_module_info mi;
386 if (!PyArg_ParseTuple(args, "s:zipimporter.is_package",
387 &fullname))
388 return NULL;
390 mi = get_module_info(self, fullname);
391 if (mi == MI_ERROR)
392 return NULL;
393 if (mi == MI_NOT_FOUND) {
394 PyErr_Format(ZipImportError, "can't find module '%.200s'",
395 fullname);
396 return NULL;
398 return PyBool_FromLong(mi == MI_PACKAGE);
401 static PyObject *
402 zipimporter_get_data(PyObject *obj, PyObject *args)
404 ZipImporter *self = (ZipImporter *)obj;
405 char *path;
406 #ifdef ALTSEP
407 char *p, buf[MAXPATHLEN + 1];
408 #endif
409 PyObject *toc_entry;
410 int len;
412 if (!PyArg_ParseTuple(args, "s:zipimporter.get_data", &path))
413 return NULL;
415 #ifdef ALTSEP
416 if (strlen(path) >= MAXPATHLEN) {
417 PyErr_SetString(ZipImportError, "path too long");
418 return NULL;
420 strcpy(buf, path);
421 for (p = buf; *p; p++) {
422 if (*p == ALTSEP)
423 *p = SEP;
425 path = buf;
426 #endif
427 len = PyString_Size(self->archive);
428 if ((size_t)len < strlen(path) &&
429 strncmp(path, PyString_AsString(self->archive), len) == 0 &&
430 path[len] == SEP) {
431 path = path + len + 1;
434 toc_entry = PyDict_GetItemString(self->files, path);
435 if (toc_entry == NULL) {
436 PyErr_Format(PyExc_IOError, "file not found [%.200s]",
437 path);
438 return NULL;
440 return get_data(PyString_AsString(self->archive), toc_entry);
443 static PyObject *
444 zipimporter_get_code(PyObject *obj, PyObject *args)
446 ZipImporter *self = (ZipImporter *)obj;
447 char *fullname;
449 if (!PyArg_ParseTuple(args, "s:zipimporter.get_code", &fullname))
450 return NULL;
452 return get_module_code(self, fullname, NULL, NULL);
455 static PyObject *
456 zipimporter_get_source(PyObject *obj, PyObject *args)
458 ZipImporter *self = (ZipImporter *)obj;
459 PyObject *toc_entry;
460 char *fullname, *subname, path[MAXPATHLEN+1];
461 int len;
462 enum zi_module_info mi;
464 if (!PyArg_ParseTuple(args, "s:zipimporter.get_source", &fullname))
465 return NULL;
467 mi = get_module_info(self, fullname);
468 if (mi == MI_ERROR)
469 return NULL;
470 if (mi == MI_NOT_FOUND) {
471 PyErr_Format(ZipImportError, "can't find module '%.200s'",
472 fullname);
473 return NULL;
475 subname = get_subname(fullname);
477 len = make_filename(PyString_AsString(self->prefix), subname, path);
478 if (len < 0)
479 return NULL;
481 if (mi == MI_PACKAGE) {
482 path[len] = SEP;
483 strcpy(path + len + 1, "__init__.py");
485 else
486 strcpy(path + len, ".py");
488 toc_entry = PyDict_GetItemString(self->files, path);
489 if (toc_entry != NULL)
490 return get_data(PyString_AsString(self->archive), toc_entry);
492 /* we have the module, but no source */
493 Py_INCREF(Py_None);
494 return Py_None;
497 PyDoc_STRVAR(doc_find_module,
498 "find_module(fullname, path=None) -> self or None.\n\
500 Search for a module specified by 'fullname'. 'fullname' must be the\n\
501 fully qualified (dotted) module name. It returns the zipimporter\n\
502 instance itself if the module was found, or None if it wasn't.\n\
503 The optional 'path' argument is ignored -- it's there for compatibility\n\
504 with the importer protocol.");
506 PyDoc_STRVAR(doc_load_module,
507 "load_module(fullname) -> module.\n\
509 Load the module specified by 'fullname'. 'fullname' must be the\n\
510 fully qualified (dotted) module name. It returns the imported\n\
511 module, or raises ZipImportError if it wasn't found.");
513 PyDoc_STRVAR(doc_get_data,
514 "get_data(pathname) -> string with file data.\n\
516 Return the data associated with 'pathname'. Raise IOError if\n\
517 the file wasn't found.");
519 PyDoc_STRVAR(doc_is_package,
520 "is_package(fullname) -> bool.\n\
522 Return True if the module specified by fullname is a package.\n\
523 Raise ZipImportError is the module couldn't be found.");
525 PyDoc_STRVAR(doc_get_code,
526 "get_code(fullname) -> code object.\n\
528 Return the code object for the specified module. Raise ZipImportError\n\
529 is the module couldn't be found.");
531 PyDoc_STRVAR(doc_get_source,
532 "get_source(fullname) -> source string.\n\
534 Return the source code for the specified module. Raise ZipImportError\n\
535 is the module couldn't be found, return None if the archive does\n\
536 contain the module, but has no source for it.");
538 static PyMethodDef zipimporter_methods[] = {
539 {"find_module", zipimporter_find_module, METH_VARARGS,
540 doc_find_module},
541 {"load_module", zipimporter_load_module, METH_VARARGS,
542 doc_load_module},
543 {"get_data", zipimporter_get_data, METH_VARARGS,
544 doc_get_data},
545 {"get_code", zipimporter_get_code, METH_VARARGS,
546 doc_get_code},
547 {"get_source", zipimporter_get_source, METH_VARARGS,
548 doc_get_source},
549 {"is_package", zipimporter_is_package, METH_VARARGS,
550 doc_is_package},
551 {NULL, NULL} /* sentinel */
554 static PyMemberDef zipimporter_members[] = {
555 {"archive", T_OBJECT, offsetof(ZipImporter, archive), READONLY},
556 {"prefix", T_OBJECT, offsetof(ZipImporter, prefix), READONLY},
557 {"_files", T_OBJECT, offsetof(ZipImporter, files), READONLY},
558 {NULL}
561 PyDoc_STRVAR(zipimporter_doc,
562 "zipimporter(archivepath) -> zipimporter object\n\
564 Create a new zipimporter instance. 'archivepath' must be a path to\n\
565 a zipfile. ZipImportError is raised if 'archivepath' doesn't point to\n\
566 a valid Zip archive.");
568 #define DEFERRED_ADDRESS(ADDR) 0
570 static PyTypeObject ZipImporter_Type = {
571 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
573 "zipimport.zipimporter",
574 sizeof(ZipImporter),
575 0, /* tp_itemsize */
576 (destructor)zipimporter_dealloc, /* tp_dealloc */
577 0, /* tp_print */
578 0, /* tp_getattr */
579 0, /* tp_setattr */
580 0, /* tp_compare */
581 (reprfunc)zipimporter_repr, /* tp_repr */
582 0, /* tp_as_number */
583 0, /* tp_as_sequence */
584 0, /* tp_as_mapping */
585 0, /* tp_hash */
586 0, /* tp_call */
587 0, /* tp_str */
588 PyObject_GenericGetAttr, /* tp_getattro */
589 0, /* tp_setattro */
590 0, /* tp_as_buffer */
591 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
592 Py_TPFLAGS_HAVE_GC, /* tp_flags */
593 zipimporter_doc, /* tp_doc */
594 zipimporter_traverse, /* tp_traverse */
595 0, /* tp_clear */
596 0, /* tp_richcompare */
597 0, /* tp_weaklistoffset */
598 0, /* tp_iter */
599 0, /* tp_iternext */
600 zipimporter_methods, /* tp_methods */
601 zipimporter_members, /* tp_members */
602 0, /* tp_getset */
603 0, /* tp_base */
604 0, /* tp_dict */
605 0, /* tp_descr_get */
606 0, /* tp_descr_set */
607 0, /* tp_dictoffset */
608 (initproc)zipimporter_init, /* tp_init */
609 PyType_GenericAlloc, /* tp_alloc */
610 PyType_GenericNew, /* tp_new */
611 PyObject_GC_Del, /* tp_free */
615 /* implementation */
617 /* Given a buffer, return the long that is represented by the first
618 4 bytes, encoded as little endian. This partially reimplements
619 marshal.c:r_long() */
620 static long
621 get_long(unsigned char *buf) {
622 long x;
623 x = buf[0];
624 x |= (long)buf[1] << 8;
625 x |= (long)buf[2] << 16;
626 x |= (long)buf[3] << 24;
627 #if SIZEOF_LONG > 4
628 /* Sign extension for 64-bit machines */
629 x |= -(x & 0x80000000L);
630 #endif
631 return x;
635 read_directory(archive) -> files dict (new reference)
637 Given a path to a Zip archive, build a dict, mapping file names
638 (local to the archive, using SEP as a separator) to toc entries.
640 A toc_entry is a tuple:
642 (__file__, # value to use for __file__, available for all files
643 compress, # compression kind; 0 for uncompressed
644 data_size, # size of compressed data on disk
645 file_size, # size of decompressed data
646 file_offset, # offset of file header from start of archive
647 time, # mod time of file (in dos format)
648 date, # mod data of file (in dos format)
649 crc, # crc checksum of the data
652 Directories can be recognized by the trailing SEP in the name,
653 data_size and file_offset are 0.
655 static PyObject *
656 read_directory(char *archive)
658 PyObject *files = NULL;
659 FILE *fp;
660 long compress, crc, data_size, file_size, file_offset, date, time;
661 long header_offset, name_size, header_size, header_position;
662 long i, l, count;
663 size_t length;
664 char path[MAXPATHLEN + 5];
665 char name[MAXPATHLEN + 5];
666 char *p, endof_central_dir[22];
667 long arc_offset; /* offset from beginning of file to start of zip-archive */
669 if (strlen(archive) > MAXPATHLEN) {
670 PyErr_SetString(PyExc_OverflowError,
671 "Zip path name is too long");
672 return NULL;
674 strcpy(path, archive);
676 fp = fopen(archive, "rb");
677 if (fp == NULL) {
678 PyErr_Format(ZipImportError, "can't open Zip file: "
679 "'%.200s'", archive);
680 return NULL;
682 fseek(fp, -22, SEEK_END);
683 header_position = ftell(fp);
684 if (fread(endof_central_dir, 1, 22, fp) != 22) {
685 fclose(fp);
686 PyErr_Format(ZipImportError, "can't read Zip file: "
687 "'%.200s'", archive);
688 return NULL;
690 if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
691 /* Bad: End of Central Dir signature */
692 fclose(fp);
693 PyErr_Format(ZipImportError, "not a Zip file: "
694 "'%.200s'", archive);
695 return NULL;
698 header_size = get_long((unsigned char *)endof_central_dir + 12);
699 header_offset = get_long((unsigned char *)endof_central_dir + 16);
700 arc_offset = header_position - header_offset - header_size;
701 header_offset += arc_offset;
703 files = PyDict_New();
704 if (files == NULL)
705 goto error;
707 length = (long)strlen(path);
708 path[length] = SEP;
710 /* Start of Central Directory */
711 count = 0;
712 for (;;) {
713 PyObject *t;
714 int err;
716 fseek(fp, header_offset, 0); /* Start of file header */
717 l = PyMarshal_ReadLongFromFile(fp);
718 if (l != 0x02014B50)
719 break; /* Bad: Central Dir File Header */
720 fseek(fp, header_offset + 10, 0);
721 compress = PyMarshal_ReadShortFromFile(fp);
722 time = PyMarshal_ReadShortFromFile(fp);
723 date = PyMarshal_ReadShortFromFile(fp);
724 crc = PyMarshal_ReadLongFromFile(fp);
725 data_size = PyMarshal_ReadLongFromFile(fp);
726 file_size = PyMarshal_ReadLongFromFile(fp);
727 name_size = PyMarshal_ReadShortFromFile(fp);
728 header_size = 46 + name_size +
729 PyMarshal_ReadShortFromFile(fp) +
730 PyMarshal_ReadShortFromFile(fp);
731 fseek(fp, header_offset + 42, 0);
732 file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
733 if (name_size > MAXPATHLEN)
734 name_size = MAXPATHLEN;
736 p = name;
737 for (i = 0; i < name_size; i++) {
738 *p = (char)getc(fp);
739 if (*p == '/')
740 *p = SEP;
741 p++;
743 *p = 0; /* Add terminating null byte */
744 header_offset += header_size;
746 strncpy(path + length + 1, name, MAXPATHLEN - length - 1);
748 t = Py_BuildValue("siiiiiii", path, compress, data_size,
749 file_size, file_offset, time, date, crc);
750 if (t == NULL)
751 goto error;
752 err = PyDict_SetItemString(files, name, t);
753 Py_DECREF(t);
754 if (err != 0)
755 goto error;
756 count++;
758 fclose(fp);
759 if (Py_VerboseFlag)
760 PySys_WriteStderr("# zipimport: found %ld names in %s\n",
761 count, archive);
762 return files;
763 error:
764 fclose(fp);
765 Py_XDECREF(files);
766 return NULL;
769 /* Return the zlib.decompress function object, or NULL if zlib couldn't
770 be imported. The function is cached when found, so subsequent calls
771 don't import zlib again. Returns a *borrowed* reference.
772 XXX This makes zlib.decompress immortal. */
773 static PyObject *
774 get_decompress_func(void)
776 static PyObject *decompress = NULL;
778 if (decompress == NULL) {
779 PyObject *zlib;
780 static int importing_zlib = 0;
782 if (importing_zlib != 0)
783 /* Someone has a zlib.py[co] in their Zip file;
784 let's avoid a stack overflow. */
785 return NULL;
786 importing_zlib = 1;
787 zlib = PyImport_ImportModule("zlib"); /* import zlib */
788 importing_zlib = 0;
789 if (zlib != NULL) {
790 decompress = PyObject_GetAttrString(zlib,
791 "decompress");
792 Py_DECREF(zlib);
794 else
795 PyErr_Clear();
796 if (Py_VerboseFlag)
797 PySys_WriteStderr("# zipimport: zlib %s\n",
798 zlib != NULL ? "available": "UNAVAILABLE");
800 return decompress;
803 /* Given a path to a Zip file and a toc_entry, return the (uncompressed)
804 data as a new reference. */
805 static PyObject *
806 get_data(char *archive, PyObject *toc_entry)
808 PyObject *raw_data, *data = NULL, *decompress;
809 char *buf;
810 FILE *fp;
811 int err, bytes_read = 0;
812 long l;
813 char *datapath;
814 long compress, data_size, file_size, file_offset;
815 long time, date, crc;
817 if (!PyArg_ParseTuple(toc_entry, "slllllll", &datapath, &compress,
818 &data_size, &file_size, &file_offset, &time,
819 &date, &crc)) {
820 return NULL;
823 fp = fopen(archive, "rb");
824 if (!fp) {
825 PyErr_Format(PyExc_IOError,
826 "zipimport: can not open file %s", archive);
827 return NULL;
830 /* Check to make sure the local file header is correct */
831 fseek(fp, file_offset, 0);
832 l = PyMarshal_ReadLongFromFile(fp);
833 if (l != 0x04034B50) {
834 /* Bad: Local File Header */
835 PyErr_Format(ZipImportError,
836 "bad local file header in %s",
837 archive);
838 fclose(fp);
839 return NULL;
841 fseek(fp, file_offset + 26, 0);
842 l = 30 + PyMarshal_ReadShortFromFile(fp) +
843 PyMarshal_ReadShortFromFile(fp); /* local header size */
844 file_offset += l; /* Start of file data */
846 raw_data = PyString_FromStringAndSize((char *)NULL, compress == 0 ?
847 data_size : data_size + 1);
848 if (raw_data == NULL) {
849 fclose(fp);
850 return NULL;
852 buf = PyString_AsString(raw_data);
854 err = fseek(fp, file_offset, 0);
855 if (err == 0)
856 bytes_read = fread(buf, 1, data_size, fp);
857 fclose(fp);
858 if (err || bytes_read != data_size) {
859 PyErr_SetString(PyExc_IOError,
860 "zipimport: can't read data");
861 Py_DECREF(raw_data);
862 return NULL;
865 if (compress != 0) {
866 buf[data_size] = 'Z'; /* saw this in zipfile.py */
867 data_size++;
869 buf[data_size] = '\0';
871 if (compress == 0) /* data is not compressed */
872 return raw_data;
874 /* Decompress with zlib */
875 decompress = get_decompress_func();
876 if (decompress == NULL) {
877 PyErr_SetString(ZipImportError,
878 "can't decompress data; "
879 "zlib not available");
880 goto error;
882 data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
883 error:
884 Py_DECREF(raw_data);
885 return data;
888 /* Lenient date/time comparison function. The precision of the mtime
889 in the archive is lower than the mtime stored in a .pyc: we
890 must allow a difference of at most one second. */
891 static int
892 eq_mtime(time_t t1, time_t t2)
894 time_t d = t1 - t2;
895 if (d < 0)
896 d = -d;
897 /* dostime only stores even seconds, so be lenient */
898 return d <= 1;
901 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
902 and return the code object. Return None if it the magic word doesn't
903 match (we do this instead of raising an exception as we fall back
904 to .py if available and we don't want to mask other errors).
905 Returns a new reference. */
906 static PyObject *
907 unmarshal_code(char *pathname, PyObject *data, time_t mtime)
909 PyObject *code;
910 char *buf = PyString_AsString(data);
911 int size = PyString_Size(data);
913 if (size <= 9) {
914 PyErr_SetString(ZipImportError,
915 "bad pyc data");
916 return NULL;
919 if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {
920 if (Py_VerboseFlag)
921 PySys_WriteStderr("# %s has bad magic\n",
922 pathname);
923 Py_INCREF(Py_None);
924 return Py_None; /* signal caller to try alternative */
927 if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),
928 mtime)) {
929 if (Py_VerboseFlag)
930 PySys_WriteStderr("# %s has bad mtime\n",
931 pathname);
932 Py_INCREF(Py_None);
933 return Py_None; /* signal caller to try alternative */
936 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
937 if (code == NULL)
938 return NULL;
939 if (!PyCode_Check(code)) {
940 Py_DECREF(code);
941 PyErr_Format(PyExc_TypeError,
942 "compiled module %.200s is not a code object",
943 pathname);
944 return NULL;
946 return code;
949 /* Replace any occurances of "\r\n?" in the input string with "\n".
950 This converts DOS and Mac line endings to Unix line endings.
951 Also append a trailing "\n" to be compatible with
952 PyParser_SimpleParseFile(). Returns a new reference. */
953 static PyObject *
954 normalize_line_endings(PyObject *source)
956 char *buf, *q, *p = PyString_AsString(source);
957 PyObject *fixed_source;
959 /* one char extra for trailing \n and one for terminating \0 */
960 buf = PyMem_Malloc(PyString_Size(source) + 2);
961 if (buf == NULL) {
962 PyErr_SetString(PyExc_MemoryError,
963 "zipimport: no memory to allocate "
964 "source buffer");
965 return NULL;
967 /* replace "\r\n?" by "\n" */
968 for (q = buf; *p != '\0'; p++) {
969 if (*p == '\r') {
970 *q++ = '\n';
971 if (*(p + 1) == '\n')
972 p++;
974 else
975 *q++ = *p;
977 *q++ = '\n'; /* add trailing \n */
978 *q = '\0';
979 fixed_source = PyString_FromString(buf);
980 PyMem_Free(buf);
981 return fixed_source;
984 /* Given a string buffer containing Python source code, compile it
985 return and return a code object as a new reference. */
986 static PyObject *
987 compile_source(char *pathname, PyObject *source)
989 PyObject *code, *fixed_source;
991 fixed_source = normalize_line_endings(source);
992 if (fixed_source == NULL)
993 return NULL;
995 code = Py_CompileString(PyString_AsString(fixed_source), pathname,
996 Py_file_input);
997 Py_DECREF(fixed_source);
998 return code;
1001 /* Convert the date/time values found in the Zip archive to a value
1002 that's compatible with the time stamp stored in .pyc files. */
1003 static time_t
1004 parse_dostime(int dostime, int dosdate)
1006 struct tm stm;
1008 stm.tm_sec = (dostime & 0x1f) * 2;
1009 stm.tm_min = (dostime >> 5) & 0x3f;
1010 stm.tm_hour = (dostime >> 11) & 0x1f;
1011 stm.tm_mday = dosdate & 0x1f;
1012 stm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;
1013 stm.tm_year = ((dosdate >> 9) & 0x7f) + 80;
1014 stm.tm_isdst = -1; /* wday/yday is ignored */
1016 return mktime(&stm);
1019 /* Given a path to a .pyc or .pyo file in the archive, return the
1020 modifictaion time of the matching .py file, or 0 if no source
1021 is available. */
1022 static time_t
1023 get_mtime_of_source(ZipImporter *self, char *path)
1025 PyObject *toc_entry;
1026 time_t mtime = 0;
1027 int lastchar = strlen(path) - 1;
1028 char savechar = path[lastchar];
1029 path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */
1030 toc_entry = PyDict_GetItemString(self->files, path);
1031 if (toc_entry != NULL && PyTuple_Check(toc_entry) &&
1032 PyTuple_Size(toc_entry) == 8) {
1033 /* fetch the time stamp of the .py file for comparison
1034 with an embedded pyc time stamp */
1035 int time, date;
1036 time = PyInt_AsLong(PyTuple_GetItem(toc_entry, 5));
1037 date = PyInt_AsLong(PyTuple_GetItem(toc_entry, 6));
1038 mtime = parse_dostime(time, date);
1040 path[lastchar] = savechar;
1041 return mtime;
1044 /* Return the code object for the module named by 'fullname' from the
1045 Zip archive as a new reference. */
1046 static PyObject *
1047 get_code_from_data(ZipImporter *self, int ispackage, int isbytecode,
1048 time_t mtime, PyObject *toc_entry)
1050 PyObject *data, *code;
1051 char *modpath;
1052 char *archive = PyString_AsString(self->archive);
1054 if (archive == NULL)
1055 return NULL;
1057 data = get_data(archive, toc_entry);
1058 if (data == NULL)
1059 return NULL;
1061 modpath = PyString_AsString(PyTuple_GetItem(toc_entry, 0));
1063 if (isbytecode) {
1064 code = unmarshal_code(modpath, data, mtime);
1066 else {
1067 code = compile_source(modpath, data);
1069 Py_DECREF(data);
1070 return code;
1073 /* Get the code object assoiciated with the module specified by
1074 'fullname'. */
1075 static PyObject *
1076 get_module_code(ZipImporter *self, char *fullname,
1077 int *p_ispackage, char **p_modpath)
1079 PyObject *toc_entry;
1080 char *subname, path[MAXPATHLEN + 1];
1081 int len;
1082 struct st_zip_searchorder *zso;
1084 subname = get_subname(fullname);
1086 len = make_filename(PyString_AsString(self->prefix), subname, path);
1087 if (len < 0)
1088 return NULL;
1090 for (zso = zip_searchorder; *zso->suffix; zso++) {
1091 PyObject *code = NULL;
1093 strcpy(path + len, zso->suffix);
1094 if (Py_VerboseFlag > 1)
1095 PySys_WriteStderr("# trying %s%c%s\n",
1096 PyString_AsString(self->archive),
1097 SEP, path);
1098 toc_entry = PyDict_GetItemString(self->files, path);
1099 if (toc_entry != NULL) {
1100 time_t mtime = 0;
1101 int ispackage = zso->type & IS_PACKAGE;
1102 int isbytecode = zso->type & IS_BYTECODE;
1104 if (isbytecode)
1105 mtime = get_mtime_of_source(self, path);
1106 if (p_ispackage != NULL)
1107 *p_ispackage = ispackage;
1108 code = get_code_from_data(self, ispackage,
1109 isbytecode, mtime,
1110 toc_entry);
1111 if (code == Py_None) {
1112 /* bad magic number or non-matching mtime
1113 in byte code, try next */
1114 Py_DECREF(code);
1115 continue;
1117 if (code != NULL && p_modpath != NULL)
1118 *p_modpath = PyString_AsString(
1119 PyTuple_GetItem(toc_entry, 0));
1120 return code;
1123 PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname);
1124 return NULL;
1128 /* Module init */
1130 PyDoc_STRVAR(zipimport_doc,
1131 "zipimport provides support for importing Python modules from Zip archives.\n\
1133 This module exports three objects:\n\
1134 - zipimporter: a class; its constructor takes a path to a Zip archive.\n\
1135 - ZipImportError: exception raised by zipimporter objects. It's a\n\
1136 subclass of ImportError, so it can be caught as ImportError, too.\n\
1137 - _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
1138 info dicts, as used in zipimporter._files.\n\
1140 It is usually not needed to use the zipimport module explicitly; it is\n\
1141 used by the builtin import mechanism for sys.path items that are paths\n\
1142 to Zip archives.");
1144 PyMODINIT_FUNC
1145 initzipimport(void)
1147 PyObject *mod;
1149 if (PyType_Ready(&ZipImporter_Type) < 0)
1150 return;
1152 /* Correct directory separator */
1153 zip_searchorder[0].suffix[0] = SEP;
1154 zip_searchorder[1].suffix[0] = SEP;
1155 zip_searchorder[2].suffix[0] = SEP;
1156 if (Py_OptimizeFlag) {
1157 /* Reverse *.pyc and *.pyo */
1158 struct st_zip_searchorder tmp;
1159 tmp = zip_searchorder[0];
1160 zip_searchorder[0] = zip_searchorder[1];
1161 zip_searchorder[1] = tmp;
1162 tmp = zip_searchorder[3];
1163 zip_searchorder[3] = zip_searchorder[4];
1164 zip_searchorder[4] = tmp;
1167 mod = Py_InitModule4("zipimport", NULL, zipimport_doc,
1168 NULL, PYTHON_API_VERSION);
1170 ZipImportError = PyErr_NewException("zipimport.ZipImportError",
1171 PyExc_ImportError, NULL);
1172 if (ZipImportError == NULL)
1173 return;
1175 Py_INCREF(ZipImportError);
1176 if (PyModule_AddObject(mod, "ZipImportError",
1177 ZipImportError) < 0)
1178 return;
1180 Py_INCREF(&ZipImporter_Type);
1181 if (PyModule_AddObject(mod, "zipimporter",
1182 (PyObject *)&ZipImporter_Type) < 0)
1183 return;
1185 zip_directory_cache = PyDict_New();
1186 if (zip_directory_cache == NULL)
1187 return;
1188 Py_INCREF(zip_directory_cache);
1189 if (PyModule_AddObject(mod, "_zip_directory_cache",
1190 zip_directory_cache) < 0)
1191 return;