ยปCore Development>Code coverage>Modules/zipimport.c

Python code coverage for Modules/zipimport.c

#countcontent
1n/a#include "Python.h"
2n/a#include "structmember.h"
3n/a#include "osdefs.h"
4n/a#include "marshal.h"
5n/a#include <time.h>
6n/a
7n/a
8n/a#define IS_SOURCE 0x0
9n/a#define IS_BYTECODE 0x1
10n/a#define IS_PACKAGE 0x2
11n/a
12n/astruct st_zip_searchorder {
13n/a char suffix[14];
14n/a int type;
15n/a};
16n/a
17n/a#ifdef ALTSEP
18n/a_Py_IDENTIFIER(replace);
19n/a#endif
20n/a
21n/a/* zip_searchorder defines how we search for a module in the Zip
22n/a archive: we first search for a package __init__, then for
23n/a non-package .pyc, and .py entries. The .pyc entries
24n/a are swapped by initzipimport() if we run in optimized mode. Also,
25n/a '/' is replaced by SEP there. */
26n/astatic struct st_zip_searchorder zip_searchorder[] = {
27n/a {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
28n/a {"/__init__.py", IS_PACKAGE | IS_SOURCE},
29n/a {".pyc", IS_BYTECODE},
30n/a {".py", IS_SOURCE},
31n/a {"", 0}
32n/a};
33n/a
34n/a/* zipimporter object definition and support */
35n/a
36n/atypedef struct _zipimporter ZipImporter;
37n/a
38n/astruct _zipimporter {
39n/a PyObject_HEAD
40n/a PyObject *archive; /* pathname of the Zip archive,
41n/a decoded from the filesystem encoding */
42n/a PyObject *prefix; /* file prefix: "a/sub/directory/",
43n/a encoded to the filesystem encoding */
44n/a PyObject *files; /* dict with file info {path: toc_entry} */
45n/a};
46n/a
47n/astatic PyObject *ZipImportError;
48n/a/* read_directory() cache */
49n/astatic PyObject *zip_directory_cache = NULL;
50n/a
51n/a/* forward decls */
52n/astatic PyObject *read_directory(PyObject *archive);
53n/astatic PyObject *get_data(PyObject *archive, PyObject *toc_entry);
54n/astatic PyObject *get_module_code(ZipImporter *self, PyObject *fullname,
55n/a int *p_ispackage, PyObject **p_modpath);
56n/a
57n/a
58n/a#define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type)
59n/a
60n/a
61n/a/* zipimporter.__init__
62n/a Split the "subdirectory" from the Zip archive path, lookup a matching
63n/a entry in sys.path_importer_cache, fetch the file directory from there
64n/a if found, or else read it from the archive. */
65n/astatic int
66n/azipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
67n/a{
68n/a PyObject *path, *files, *tmp;
69n/a PyObject *filename = NULL;
70n/a Py_ssize_t len, flen;
71n/a
72n/a if (!_PyArg_NoKeywords("zipimporter()", kwds))
73n/a return -1;
74n/a
75n/a if (!PyArg_ParseTuple(args, "O&:zipimporter",
76n/a PyUnicode_FSDecoder, &path))
77n/a return -1;
78n/a
79n/a if (PyUnicode_READY(path) == -1)
80n/a return -1;
81n/a
82n/a len = PyUnicode_GET_LENGTH(path);
83n/a if (len == 0) {
84n/a PyErr_SetString(ZipImportError, "archive path is empty");
85n/a goto error;
86n/a }
87n/a
88n/a#ifdef ALTSEP
89n/a tmp = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP);
90n/a if (!tmp)
91n/a goto error;
92n/a Py_DECREF(path);
93n/a path = tmp;
94n/a#endif
95n/a
96n/a filename = path;
97n/a Py_INCREF(filename);
98n/a flen = len;
99n/a for (;;) {
100n/a struct stat statbuf;
101n/a int rv;
102n/a
103n/a rv = _Py_stat(filename, &statbuf);
104n/a if (rv == -2)
105n/a goto error;
106n/a if (rv == 0) {
107n/a /* it exists */
108n/a if (!S_ISREG(statbuf.st_mode))
109n/a /* it's a not file */
110n/a Py_CLEAR(filename);
111n/a break;
112n/a }
113n/a Py_CLEAR(filename);
114n/a /* back up one path element */
115n/a flen = PyUnicode_FindChar(path, SEP, 0, flen, -1);
116n/a if (flen == -1)
117n/a break;
118n/a filename = PyUnicode_Substring(path, 0, flen);
119n/a if (filename == NULL)
120n/a goto error;
121n/a }
122n/a if (filename == NULL) {
123n/a PyErr_SetString(ZipImportError, "not a Zip file");
124n/a goto error;
125n/a }
126n/a
127n/a if (PyUnicode_READY(filename) < 0)
128n/a goto error;
129n/a
130n/a files = PyDict_GetItem(zip_directory_cache, filename);
131n/a if (files == NULL) {
132n/a files = read_directory(filename);
133n/a if (files == NULL)
134n/a goto error;
135n/a if (PyDict_SetItem(zip_directory_cache, filename, files) != 0)
136n/a goto error;
137n/a }
138n/a else
139n/a Py_INCREF(files);
140n/a self->files = files;
141n/a
142n/a /* Transfer reference */
143n/a self->archive = filename;
144n/a filename = NULL;
145n/a
146n/a /* Check if there is a prefix directory following the filename. */
147n/a if (flen != len) {
148n/a tmp = PyUnicode_Substring(path, flen+1,
149n/a PyUnicode_GET_LENGTH(path));
150n/a if (tmp == NULL)
151n/a goto error;
152n/a self->prefix = tmp;
153n/a if (PyUnicode_READ_CHAR(path, len-1) != SEP) {
154n/a /* add trailing SEP */
155n/a tmp = PyUnicode_FromFormat("%U%c", self->prefix, SEP);
156n/a if (tmp == NULL)
157n/a goto error;
158n/a Py_SETREF(self->prefix, tmp);
159n/a }
160n/a }
161n/a else
162n/a self->prefix = PyUnicode_New(0, 0);
163n/a Py_DECREF(path);
164n/a return 0;
165n/a
166n/aerror:
167n/a Py_DECREF(path);
168n/a Py_XDECREF(filename);
169n/a return -1;
170n/a}
171n/a
172n/a/* GC support. */
173n/astatic int
174n/azipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
175n/a{
176n/a ZipImporter *self = (ZipImporter *)obj;
177n/a Py_VISIT(self->files);
178n/a return 0;
179n/a}
180n/a
181n/astatic void
182n/azipimporter_dealloc(ZipImporter *self)
183n/a{
184n/a PyObject_GC_UnTrack(self);
185n/a Py_XDECREF(self->archive);
186n/a Py_XDECREF(self->prefix);
187n/a Py_XDECREF(self->files);
188n/a Py_TYPE(self)->tp_free((PyObject *)self);
189n/a}
190n/a
191n/astatic PyObject *
192n/azipimporter_repr(ZipImporter *self)
193n/a{
194n/a if (self->archive == NULL)
195n/a return PyUnicode_FromString("<zipimporter object \"???\">");
196n/a else if (self->prefix != NULL && PyUnicode_GET_LENGTH(self->prefix) != 0)
197n/a return PyUnicode_FromFormat("<zipimporter object \"%U%c%U\">",
198n/a self->archive, SEP, self->prefix);
199n/a else
200n/a return PyUnicode_FromFormat("<zipimporter object \"%U\">",
201n/a self->archive);
202n/a}
203n/a
204n/a/* return fullname.split(".")[-1] */
205n/astatic PyObject *
206n/aget_subname(PyObject *fullname)
207n/a{
208n/a Py_ssize_t len, dot;
209n/a if (PyUnicode_READY(fullname) < 0)
210n/a return NULL;
211n/a len = PyUnicode_GET_LENGTH(fullname);
212n/a dot = PyUnicode_FindChar(fullname, '.', 0, len, -1);
213n/a if (dot == -1) {
214n/a Py_INCREF(fullname);
215n/a return fullname;
216n/a } else
217n/a return PyUnicode_Substring(fullname, dot+1, len);
218n/a}
219n/a
220n/a/* Given a (sub)modulename, write the potential file path in the
221n/a archive (without extension) to the path buffer. Return the
222n/a length of the resulting string.
223n/a
224n/a return self.prefix + name.replace('.', os.sep) */
225n/astatic PyObject*
226n/amake_filename(PyObject *prefix, PyObject *name)
227n/a{
228n/a PyObject *pathobj;
229n/a Py_UCS4 *p, *buf;
230n/a Py_ssize_t len;
231n/a
232n/a len = PyUnicode_GET_LENGTH(prefix) + PyUnicode_GET_LENGTH(name) + 1;
233n/a p = buf = PyMem_New(Py_UCS4, len);
234n/a if (buf == NULL) {
235n/a PyErr_NoMemory();
236n/a return NULL;
237n/a }
238n/a
239n/a if (!PyUnicode_AsUCS4(prefix, p, len, 0)) {
240n/a PyMem_Free(buf);
241n/a return NULL;
242n/a }
243n/a p += PyUnicode_GET_LENGTH(prefix);
244n/a len -= PyUnicode_GET_LENGTH(prefix);
245n/a if (!PyUnicode_AsUCS4(name, p, len, 1)) {
246n/a PyMem_Free(buf);
247n/a return NULL;
248n/a }
249n/a for (; *p; p++) {
250n/a if (*p == '.')
251n/a *p = SEP;
252n/a }
253n/a pathobj = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
254n/a buf, p-buf);
255n/a PyMem_Free(buf);
256n/a return pathobj;
257n/a}
258n/a
259n/aenum zi_module_info {
260n/a MI_ERROR,
261n/a MI_NOT_FOUND,
262n/a MI_MODULE,
263n/a MI_PACKAGE
264n/a};
265n/a
266n/a/* Does this path represent a directory?
267n/a on error, return < 0
268n/a if not a dir, return 0
269n/a if a dir, return 1
270n/a*/
271n/astatic int
272n/acheck_is_directory(ZipImporter *self, PyObject* prefix, PyObject *path)
273n/a{
274n/a PyObject *dirpath;
275n/a int res;
276n/a
277n/a /* See if this is a "directory". If so, it's eligible to be part
278n/a of a namespace package. We test by seeing if the name, with an
279n/a appended path separator, exists. */
280n/a dirpath = PyUnicode_FromFormat("%U%U%c", prefix, path, SEP);
281n/a if (dirpath == NULL)
282n/a return -1;
283n/a /* If dirpath is present in self->files, we have a directory. */
284n/a res = PyDict_Contains(self->files, dirpath);
285n/a Py_DECREF(dirpath);
286n/a return res;
287n/a}
288n/a
289n/a/* Return some information about a module. */
290n/astatic enum zi_module_info
291n/aget_module_info(ZipImporter *self, PyObject *fullname)
292n/a{
293n/a PyObject *subname;
294n/a PyObject *path, *fullpath, *item;
295n/a struct st_zip_searchorder *zso;
296n/a
297n/a subname = get_subname(fullname);
298n/a if (subname == NULL)
299n/a return MI_ERROR;
300n/a
301n/a path = make_filename(self->prefix, subname);
302n/a Py_DECREF(subname);
303n/a if (path == NULL)
304n/a return MI_ERROR;
305n/a
306n/a for (zso = zip_searchorder; *zso->suffix; zso++) {
307n/a fullpath = PyUnicode_FromFormat("%U%s", path, zso->suffix);
308n/a if (fullpath == NULL) {
309n/a Py_DECREF(path);
310n/a return MI_ERROR;
311n/a }
312n/a item = PyDict_GetItem(self->files, fullpath);
313n/a Py_DECREF(fullpath);
314n/a if (item != NULL) {
315n/a Py_DECREF(path);
316n/a if (zso->type & IS_PACKAGE)
317n/a return MI_PACKAGE;
318n/a else
319n/a return MI_MODULE;
320n/a }
321n/a }
322n/a Py_DECREF(path);
323n/a return MI_NOT_FOUND;
324n/a}
325n/a
326n/atypedef enum {
327n/a FL_ERROR = -1, /* error */
328n/a FL_NOT_FOUND, /* no loader or namespace portions found */
329n/a FL_MODULE_FOUND, /* module/package found */
330n/a FL_NS_FOUND /* namespace portion found: */
331n/a /* *namespace_portion will point to the name */
332n/a} find_loader_result;
333n/a
334n/a/* The guts of "find_loader" and "find_module".
335n/a*/
336n/astatic find_loader_result
337n/afind_loader(ZipImporter *self, PyObject *fullname, PyObject **namespace_portion)
338n/a{
339n/a enum zi_module_info mi;
340n/a
341n/a *namespace_portion = NULL;
342n/a
343n/a mi = get_module_info(self, fullname);
344n/a if (mi == MI_ERROR)
345n/a return FL_ERROR;
346n/a if (mi == MI_NOT_FOUND) {
347n/a /* Not a module or regular package. See if this is a directory, and
348n/a therefore possibly a portion of a namespace package. */
349n/a find_loader_result result = FL_NOT_FOUND;
350n/a PyObject *subname;
351n/a int is_dir;
352n/a
353n/a /* We're only interested in the last path component of fullname;
354n/a earlier components are recorded in self->prefix. */
355n/a subname = get_subname(fullname);
356n/a if (subname == NULL) {
357n/a return FL_ERROR;
358n/a }
359n/a
360n/a is_dir = check_is_directory(self, self->prefix, subname);
361n/a if (is_dir < 0)
362n/a result = FL_ERROR;
363n/a else if (is_dir) {
364n/a /* This is possibly a portion of a namespace
365n/a package. Return the string representing its path,
366n/a without a trailing separator. */
367n/a *namespace_portion = PyUnicode_FromFormat("%U%c%U%U",
368n/a self->archive, SEP,
369n/a self->prefix, subname);
370n/a if (*namespace_portion == NULL)
371n/a result = FL_ERROR;
372n/a else
373n/a result = FL_NS_FOUND;
374n/a }
375n/a Py_DECREF(subname);
376n/a return result;
377n/a }
378n/a /* This is a module or package. */
379n/a return FL_MODULE_FOUND;
380n/a}
381n/a
382n/a
383n/a/* Check whether we can satisfy the import of the module named by
384n/a 'fullname'. Return self if we can, None if we can't. */
385n/astatic PyObject *
386n/azipimporter_find_module(PyObject *obj, PyObject *args)
387n/a{
388n/a ZipImporter *self = (ZipImporter *)obj;
389n/a PyObject *path = NULL;
390n/a PyObject *fullname;
391n/a PyObject *namespace_portion = NULL;
392n/a PyObject *result = NULL;
393n/a
394n/a if (!PyArg_ParseTuple(args, "U|O:zipimporter.find_module", &fullname, &path))
395n/a return NULL;
396n/a
397n/a switch (find_loader(self, fullname, &namespace_portion)) {
398n/a case FL_ERROR:
399n/a return NULL;
400n/a case FL_NS_FOUND:
401n/a /* A namespace portion is not allowed via find_module, so return None. */
402n/a Py_DECREF(namespace_portion);
403n/a /* FALL THROUGH */
404n/a case FL_NOT_FOUND:
405n/a result = Py_None;
406n/a break;
407n/a case FL_MODULE_FOUND:
408n/a result = (PyObject *)self;
409n/a break;
410n/a default:
411n/a PyErr_BadInternalCall();
412n/a return NULL;
413n/a }
414n/a Py_INCREF(result);
415n/a return result;
416n/a}
417n/a
418n/a
419n/a/* Check whether we can satisfy the import of the module named by
420n/a 'fullname', or whether it could be a portion of a namespace
421n/a package. Return self if we can load it, a string containing the
422n/a full path if it's a possible namespace portion, None if we
423n/a can't load it. */
424n/astatic PyObject *
425n/azipimporter_find_loader(PyObject *obj, PyObject *args)
426n/a{
427n/a ZipImporter *self = (ZipImporter *)obj;
428n/a PyObject *path = NULL;
429n/a PyObject *fullname;
430n/a PyObject *result = NULL;
431n/a PyObject *namespace_portion = NULL;
432n/a
433n/a if (!PyArg_ParseTuple(args, "U|O:zipimporter.find_module", &fullname, &path))
434n/a return NULL;
435n/a
436n/a switch (find_loader(self, fullname, &namespace_portion)) {
437n/a case FL_ERROR:
438n/a return NULL;
439n/a case FL_NOT_FOUND: /* Not found, return (None, []) */
440n/a result = Py_BuildValue("O[]", Py_None);
441n/a break;
442n/a case FL_MODULE_FOUND: /* Return (self, []) */
443n/a result = Py_BuildValue("O[]", self);
444n/a break;
445n/a case FL_NS_FOUND: /* Return (None, [namespace_portion]) */
446n/a result = Py_BuildValue("O[O]", Py_None, namespace_portion);
447n/a Py_DECREF(namespace_portion);
448n/a return result;
449n/a default:
450n/a PyErr_BadInternalCall();
451n/a return NULL;
452n/a }
453n/a return result;
454n/a}
455n/a
456n/a/* Load and return the module named by 'fullname'. */
457n/astatic PyObject *
458n/azipimporter_load_module(PyObject *obj, PyObject *args)
459n/a{
460n/a ZipImporter *self = (ZipImporter *)obj;
461n/a PyObject *code = NULL, *mod, *dict;
462n/a PyObject *fullname;
463n/a PyObject *modpath = NULL;
464n/a int ispackage;
465n/a
466n/a if (!PyArg_ParseTuple(args, "U:zipimporter.load_module",
467n/a &fullname))
468n/a return NULL;
469n/a if (PyUnicode_READY(fullname) == -1)
470n/a return NULL;
471n/a
472n/a code = get_module_code(self, fullname, &ispackage, &modpath);
473n/a if (code == NULL)
474n/a goto error;
475n/a
476n/a mod = PyImport_AddModuleObject(fullname);
477n/a if (mod == NULL)
478n/a goto error;
479n/a dict = PyModule_GetDict(mod);
480n/a
481n/a /* mod.__loader__ = self */
482n/a if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
483n/a goto error;
484n/a
485n/a if (ispackage) {
486n/a /* add __path__ to the module *before* the code gets
487n/a executed */
488n/a PyObject *pkgpath, *fullpath, *subname;
489n/a int err;
490n/a
491n/a subname = get_subname(fullname);
492n/a if (subname == NULL)
493n/a goto error;
494n/a
495n/a fullpath = PyUnicode_FromFormat("%U%c%U%U",
496n/a self->archive, SEP,
497n/a self->prefix, subname);
498n/a Py_DECREF(subname);
499n/a if (fullpath == NULL)
500n/a goto error;
501n/a
502n/a pkgpath = Py_BuildValue("[N]", fullpath);
503n/a if (pkgpath == NULL)
504n/a goto error;
505n/a err = PyDict_SetItemString(dict, "__path__", pkgpath);
506n/a Py_DECREF(pkgpath);
507n/a if (err != 0)
508n/a goto error;
509n/a }
510n/a mod = PyImport_ExecCodeModuleObject(fullname, code, modpath, NULL);
511n/a Py_CLEAR(code);
512n/a if (mod == NULL)
513n/a goto error;
514n/a
515n/a if (Py_VerboseFlag)
516n/a PySys_FormatStderr("import %U # loaded from Zip %U\n",
517n/a fullname, modpath);
518n/a Py_DECREF(modpath);
519n/a return mod;
520n/aerror:
521n/a Py_XDECREF(code);
522n/a Py_XDECREF(modpath);
523n/a return NULL;
524n/a}
525n/a
526n/a/* Return a string matching __file__ for the named module */
527n/astatic PyObject *
528n/azipimporter_get_filename(PyObject *obj, PyObject *args)
529n/a{
530n/a ZipImporter *self = (ZipImporter *)obj;
531n/a PyObject *fullname, *code, *modpath;
532n/a int ispackage;
533n/a
534n/a if (!PyArg_ParseTuple(args, "U:zipimporter.get_filename",
535n/a &fullname))
536n/a return NULL;
537n/a
538n/a /* Deciding the filename requires working out where the code
539n/a would come from if the module was actually loaded */
540n/a code = get_module_code(self, fullname, &ispackage, &modpath);
541n/a if (code == NULL)
542n/a return NULL;
543n/a Py_DECREF(code); /* Only need the path info */
544n/a
545n/a return modpath;
546n/a}
547n/a
548n/a/* Return a bool signifying whether the module is a package or not. */
549n/astatic PyObject *
550n/azipimporter_is_package(PyObject *obj, PyObject *args)
551n/a{
552n/a ZipImporter *self = (ZipImporter *)obj;
553n/a PyObject *fullname;
554n/a enum zi_module_info mi;
555n/a
556n/a if (!PyArg_ParseTuple(args, "U:zipimporter.is_package",
557n/a &fullname))
558n/a return NULL;
559n/a
560n/a mi = get_module_info(self, fullname);
561n/a if (mi == MI_ERROR)
562n/a return NULL;
563n/a if (mi == MI_NOT_FOUND) {
564n/a PyErr_Format(ZipImportError, "can't find module %R", fullname);
565n/a return NULL;
566n/a }
567n/a return PyBool_FromLong(mi == MI_PACKAGE);
568n/a}
569n/a
570n/a
571n/astatic PyObject *
572n/azipimporter_get_data(PyObject *obj, PyObject *args)
573n/a{
574n/a ZipImporter *self = (ZipImporter *)obj;
575n/a PyObject *path, *key;
576n/a PyObject *toc_entry;
577n/a Py_ssize_t path_start, path_len, len;
578n/a
579n/a if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path))
580n/a return NULL;
581n/a
582n/a#ifdef ALTSEP
583n/a path = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP);
584n/a if (!path)
585n/a return NULL;
586n/a#else
587n/a Py_INCREF(path);
588n/a#endif
589n/a if (PyUnicode_READY(path) == -1)
590n/a goto error;
591n/a
592n/a path_len = PyUnicode_GET_LENGTH(path);
593n/a
594n/a len = PyUnicode_GET_LENGTH(self->archive);
595n/a path_start = 0;
596n/a if (PyUnicode_Tailmatch(path, self->archive, 0, len, -1)
597n/a && PyUnicode_READ_CHAR(path, len) == SEP) {
598n/a path_start = len + 1;
599n/a }
600n/a
601n/a key = PyUnicode_Substring(path, path_start, path_len);
602n/a if (key == NULL)
603n/a goto error;
604n/a toc_entry = PyDict_GetItem(self->files, key);
605n/a if (toc_entry == NULL) {
606n/a PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key);
607n/a Py_DECREF(key);
608n/a goto error;
609n/a }
610n/a Py_DECREF(key);
611n/a Py_DECREF(path);
612n/a return get_data(self->archive, toc_entry);
613n/a error:
614n/a Py_DECREF(path);
615n/a return NULL;
616n/a}
617n/a
618n/astatic PyObject *
619n/azipimporter_get_code(PyObject *obj, PyObject *args)
620n/a{
621n/a ZipImporter *self = (ZipImporter *)obj;
622n/a PyObject *fullname;
623n/a
624n/a if (!PyArg_ParseTuple(args, "U:zipimporter.get_code", &fullname))
625n/a return NULL;
626n/a
627n/a return get_module_code(self, fullname, NULL, NULL);
628n/a}
629n/a
630n/astatic PyObject *
631n/azipimporter_get_source(PyObject *obj, PyObject *args)
632n/a{
633n/a ZipImporter *self = (ZipImporter *)obj;
634n/a PyObject *toc_entry;
635n/a PyObject *fullname, *subname, *path, *fullpath;
636n/a enum zi_module_info mi;
637n/a
638n/a if (!PyArg_ParseTuple(args, "U:zipimporter.get_source", &fullname))
639n/a return NULL;
640n/a
641n/a mi = get_module_info(self, fullname);
642n/a if (mi == MI_ERROR)
643n/a return NULL;
644n/a if (mi == MI_NOT_FOUND) {
645n/a PyErr_Format(ZipImportError, "can't find module %R", fullname);
646n/a return NULL;
647n/a }
648n/a
649n/a subname = get_subname(fullname);
650n/a if (subname == NULL)
651n/a return NULL;
652n/a
653n/a path = make_filename(self->prefix, subname);
654n/a Py_DECREF(subname);
655n/a if (path == NULL)
656n/a return NULL;
657n/a
658n/a if (mi == MI_PACKAGE)
659n/a fullpath = PyUnicode_FromFormat("%U%c__init__.py", path, SEP);
660n/a else
661n/a fullpath = PyUnicode_FromFormat("%U.py", path);
662n/a Py_DECREF(path);
663n/a if (fullpath == NULL)
664n/a return NULL;
665n/a
666n/a toc_entry = PyDict_GetItem(self->files, fullpath);
667n/a Py_DECREF(fullpath);
668n/a if (toc_entry != NULL) {
669n/a PyObject *res, *bytes;
670n/a bytes = get_data(self->archive, toc_entry);
671n/a if (bytes == NULL)
672n/a return NULL;
673n/a res = PyUnicode_FromStringAndSize(PyBytes_AS_STRING(bytes),
674n/a PyBytes_GET_SIZE(bytes));
675n/a Py_DECREF(bytes);
676n/a return res;
677n/a }
678n/a
679n/a /* we have the module, but no source */
680n/a Py_RETURN_NONE;
681n/a}
682n/a
683n/aPyDoc_STRVAR(doc_find_module,
684n/a"find_module(fullname, path=None) -> self or None.\n\
685n/a\n\
686n/aSearch for a module specified by 'fullname'. 'fullname' must be the\n\
687n/afully qualified (dotted) module name. It returns the zipimporter\n\
688n/ainstance itself if the module was found, or None if it wasn't.\n\
689n/aThe optional 'path' argument is ignored -- it's there for compatibility\n\
690n/awith the importer protocol.");
691n/a
692n/aPyDoc_STRVAR(doc_find_loader,
693n/a"find_loader(fullname, path=None) -> self, str or None.\n\
694n/a\n\
695n/aSearch for a module specified by 'fullname'. 'fullname' must be the\n\
696n/afully qualified (dotted) module name. It returns the zipimporter\n\
697n/ainstance itself if the module was found, a string containing the\n\
698n/afull path name if it's possibly a portion of a namespace package,\n\
699n/aor None otherwise. The optional 'path' argument is ignored -- it's\n\
700n/a there for compatibility with the importer protocol.");
701n/a
702n/aPyDoc_STRVAR(doc_load_module,
703n/a"load_module(fullname) -> module.\n\
704n/a\n\
705n/aLoad the module specified by 'fullname'. 'fullname' must be the\n\
706n/afully qualified (dotted) module name. It returns the imported\n\
707n/amodule, or raises ZipImportError if it wasn't found.");
708n/a
709n/aPyDoc_STRVAR(doc_get_data,
710n/a"get_data(pathname) -> string with file data.\n\
711n/a\n\
712n/aReturn the data associated with 'pathname'. Raise IOError if\n\
713n/athe file wasn't found.");
714n/a
715n/aPyDoc_STRVAR(doc_is_package,
716n/a"is_package(fullname) -> bool.\n\
717n/a\n\
718n/aReturn True if the module specified by fullname is a package.\n\
719n/aRaise ZipImportError if the module couldn't be found.");
720n/a
721n/aPyDoc_STRVAR(doc_get_code,
722n/a"get_code(fullname) -> code object.\n\
723n/a\n\
724n/aReturn the code object for the specified module. Raise ZipImportError\n\
725n/aif the module couldn't be found.");
726n/a
727n/aPyDoc_STRVAR(doc_get_source,
728n/a"get_source(fullname) -> source string.\n\
729n/a\n\
730n/aReturn the source code for the specified module. Raise ZipImportError\n\
731n/aif the module couldn't be found, return None if the archive does\n\
732n/acontain the module, but has no source for it.");
733n/a
734n/a
735n/aPyDoc_STRVAR(doc_get_filename,
736n/a"get_filename(fullname) -> filename string.\n\
737n/a\n\
738n/aReturn the filename for the specified module.");
739n/a
740n/astatic PyMethodDef zipimporter_methods[] = {
741n/a {"find_module", zipimporter_find_module, METH_VARARGS,
742n/a doc_find_module},
743n/a {"find_loader", zipimporter_find_loader, METH_VARARGS,
744n/a doc_find_loader},
745n/a {"load_module", zipimporter_load_module, METH_VARARGS,
746n/a doc_load_module},
747n/a {"get_data", zipimporter_get_data, METH_VARARGS,
748n/a doc_get_data},
749n/a {"get_code", zipimporter_get_code, METH_VARARGS,
750n/a doc_get_code},
751n/a {"get_source", zipimporter_get_source, METH_VARARGS,
752n/a doc_get_source},
753n/a {"get_filename", zipimporter_get_filename, METH_VARARGS,
754n/a doc_get_filename},
755n/a {"is_package", zipimporter_is_package, METH_VARARGS,
756n/a doc_is_package},
757n/a {NULL, NULL} /* sentinel */
758n/a};
759n/a
760n/astatic PyMemberDef zipimporter_members[] = {
761n/a {"archive", T_OBJECT, offsetof(ZipImporter, archive), READONLY},
762n/a {"prefix", T_OBJECT, offsetof(ZipImporter, prefix), READONLY},
763n/a {"_files", T_OBJECT, offsetof(ZipImporter, files), READONLY},
764n/a {NULL}
765n/a};
766n/a
767n/aPyDoc_STRVAR(zipimporter_doc,
768n/a"zipimporter(archivepath) -> zipimporter object\n\
769n/a\n\
770n/aCreate a new zipimporter instance. 'archivepath' must be a path to\n\
771n/aa zipfile, or to a specific path inside a zipfile. For example, it can be\n\
772n/a'/tmp/myimport.zip', or '/tmp/myimport.zip/mydirectory', if mydirectory is a\n\
773n/avalid directory inside the archive.\n\
774n/a\n\
775n/a'ZipImportError is raised if 'archivepath' doesn't point to a valid Zip\n\
776n/aarchive.\n\
777n/a\n\
778n/aThe 'archive' attribute of zipimporter objects contains the name of the\n\
779n/azipfile targeted.");
780n/a
781n/a#define DEFERRED_ADDRESS(ADDR) 0
782n/a
783n/astatic PyTypeObject ZipImporter_Type = {
784n/a PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
785n/a "zipimport.zipimporter",
786n/a sizeof(ZipImporter),
787n/a 0, /* tp_itemsize */
788n/a (destructor)zipimporter_dealloc, /* tp_dealloc */
789n/a 0, /* tp_print */
790n/a 0, /* tp_getattr */
791n/a 0, /* tp_setattr */
792n/a 0, /* tp_reserved */
793n/a (reprfunc)zipimporter_repr, /* tp_repr */
794n/a 0, /* tp_as_number */
795n/a 0, /* tp_as_sequence */
796n/a 0, /* tp_as_mapping */
797n/a 0, /* tp_hash */
798n/a 0, /* tp_call */
799n/a 0, /* tp_str */
800n/a PyObject_GenericGetAttr, /* tp_getattro */
801n/a 0, /* tp_setattro */
802n/a 0, /* tp_as_buffer */
803n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
804n/a Py_TPFLAGS_HAVE_GC, /* tp_flags */
805n/a zipimporter_doc, /* tp_doc */
806n/a zipimporter_traverse, /* tp_traverse */
807n/a 0, /* tp_clear */
808n/a 0, /* tp_richcompare */
809n/a 0, /* tp_weaklistoffset */
810n/a 0, /* tp_iter */
811n/a 0, /* tp_iternext */
812n/a zipimporter_methods, /* tp_methods */
813n/a zipimporter_members, /* tp_members */
814n/a 0, /* tp_getset */
815n/a 0, /* tp_base */
816n/a 0, /* tp_dict */
817n/a 0, /* tp_descr_get */
818n/a 0, /* tp_descr_set */
819n/a 0, /* tp_dictoffset */
820n/a (initproc)zipimporter_init, /* tp_init */
821n/a PyType_GenericAlloc, /* tp_alloc */
822n/a PyType_GenericNew, /* tp_new */
823n/a PyObject_GC_Del, /* tp_free */
824n/a};
825n/a
826n/a
827n/a/* implementation */
828n/a
829n/a/* Given a buffer, return the unsigned int that is represented by the first
830n/a 4 bytes, encoded as little endian. This partially reimplements
831n/a marshal.c:r_long() */
832n/astatic unsigned int
833n/aget_uint32(const unsigned char *buf)
834n/a{
835n/a unsigned int x;
836n/a x = buf[0];
837n/a x |= (unsigned int)buf[1] << 8;
838n/a x |= (unsigned int)buf[2] << 16;
839n/a x |= (unsigned int)buf[3] << 24;
840n/a return x;
841n/a}
842n/a
843n/a/* Given a buffer, return the unsigned int that is represented by the first
844n/a 2 bytes, encoded as little endian. This partially reimplements
845n/a marshal.c:r_short() */
846n/astatic unsigned short
847n/aget_uint16(const unsigned char *buf)
848n/a{
849n/a unsigned short x;
850n/a x = buf[0];
851n/a x |= (unsigned short)buf[1] << 8;
852n/a return x;
853n/a}
854n/a
855n/astatic void
856n/aset_file_error(PyObject *archive, int eof)
857n/a{
858n/a if (eof) {
859n/a PyErr_SetString(PyExc_EOFError, "EOF read where not expected");
860n/a }
861n/a else {
862n/a PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, archive);
863n/a }
864n/a}
865n/a
866n/a/*
867n/a read_directory(archive) -> files dict (new reference)
868n/a
869n/a Given a path to a Zip archive, build a dict, mapping file names
870n/a (local to the archive, using SEP as a separator) to toc entries.
871n/a
872n/a A toc_entry is a tuple:
873n/a
874n/a (__file__, # value to use for __file__, available for all files,
875n/a # encoded to the filesystem encoding
876n/a compress, # compression kind; 0 for uncompressed
877n/a data_size, # size of compressed data on disk
878n/a file_size, # size of decompressed data
879n/a file_offset, # offset of file header from start of archive
880n/a time, # mod time of file (in dos format)
881n/a date, # mod data of file (in dos format)
882n/a crc, # crc checksum of the data
883n/a )
884n/a
885n/a Directories can be recognized by the trailing SEP in the name,
886n/a data_size and file_offset are 0.
887n/a*/
888n/astatic PyObject *
889n/aread_directory(PyObject *archive)
890n/a{
891n/a PyObject *files = NULL;
892n/a FILE *fp;
893n/a unsigned short flags, compress, time, date, name_size;
894n/a unsigned int crc, data_size, file_size, header_size, header_offset;
895n/a unsigned long file_offset, header_position;
896n/a unsigned long arc_offset; /* Absolute offset to start of the zip-archive. */
897n/a unsigned int count, i;
898n/a unsigned char buffer[46];
899n/a char name[MAXPATHLEN + 5];
900n/a PyObject *nameobj = NULL;
901n/a PyObject *path;
902n/a const char *charset;
903n/a int bootstrap;
904n/a const char *errmsg = NULL;
905n/a
906n/a fp = _Py_fopen_obj(archive, "rb");
907n/a if (fp == NULL) {
908n/a if (PyErr_ExceptionMatches(PyExc_OSError)) {
909n/a _PyErr_FormatFromCause(ZipImportError,
910n/a "can't open Zip file: %R", archive);
911n/a }
912n/a return NULL;
913n/a }
914n/a
915n/a if (fseek(fp, -22, SEEK_END) == -1) {
916n/a goto file_error;
917n/a }
918n/a header_position = (unsigned long)ftell(fp);
919n/a if (header_position == (unsigned long)-1) {
920n/a goto file_error;
921n/a }
922n/a assert(header_position <= (unsigned long)LONG_MAX);
923n/a if (fread(buffer, 1, 22, fp) != 22) {
924n/a goto file_error;
925n/a }
926n/a if (get_uint32(buffer) != 0x06054B50u) {
927n/a /* Bad: End of Central Dir signature */
928n/a errmsg = "not a Zip file";
929n/a goto invalid_header;
930n/a }
931n/a
932n/a header_size = get_uint32(buffer + 12);
933n/a header_offset = get_uint32(buffer + 16);
934n/a if (header_position < header_size) {
935n/a errmsg = "bad central directory size";
936n/a goto invalid_header;
937n/a }
938n/a if (header_position < header_offset) {
939n/a errmsg = "bad central directory offset";
940n/a goto invalid_header;
941n/a }
942n/a if (header_position - header_size < header_offset) {
943n/a errmsg = "bad central directory size or offset";
944n/a goto invalid_header;
945n/a }
946n/a header_position -= header_size;
947n/a arc_offset = header_position - header_offset;
948n/a
949n/a files = PyDict_New();
950n/a if (files == NULL) {
951n/a goto error;
952n/a }
953n/a /* Start of Central Directory */
954n/a count = 0;
955n/a if (fseek(fp, (long)header_position, 0) == -1) {
956n/a goto file_error;
957n/a }
958n/a for (;;) {
959n/a PyObject *t;
960n/a size_t n;
961n/a int err;
962n/a
963n/a n = fread(buffer, 1, 46, fp);
964n/a if (n < 4) {
965n/a goto eof_error;
966n/a }
967n/a /* Start of file header */
968n/a if (get_uint32(buffer) != 0x02014B50u) {
969n/a break; /* Bad: Central Dir File Header */
970n/a }
971n/a if (n != 46) {
972n/a goto eof_error;
973n/a }
974n/a flags = get_uint16(buffer + 8);
975n/a compress = get_uint16(buffer + 10);
976n/a time = get_uint16(buffer + 12);
977n/a date = get_uint16(buffer + 14);
978n/a crc = get_uint32(buffer + 16);
979n/a data_size = get_uint32(buffer + 20);
980n/a file_size = get_uint32(buffer + 24);
981n/a name_size = get_uint16(buffer + 28);
982n/a header_size = (unsigned int)name_size +
983n/a get_uint16(buffer + 30) /* extra field */ +
984n/a get_uint16(buffer + 32) /* comment */;
985n/a
986n/a file_offset = get_uint32(buffer + 42);
987n/a if (file_offset > header_offset) {
988n/a errmsg = "bad local header offset";
989n/a goto invalid_header;
990n/a }
991n/a file_offset += arc_offset;
992n/a
993n/a if (name_size > MAXPATHLEN) {
994n/a name_size = MAXPATHLEN;
995n/a }
996n/a if (fread(name, 1, name_size, fp) != name_size) {
997n/a goto file_error;
998n/a }
999n/a name[name_size] = '\0'; /* Add terminating null byte */
1000n/a#if SEP != '/'
1001n/a for (i = 0; i < name_size; i++) {
1002n/a if (name[i] == '/') {
1003n/a name[i] = SEP;
1004n/a }
1005n/a }
1006n/a#endif
1007n/a /* Skip the rest of the header.
1008n/a * On Windows, calling fseek to skip over the fields we don't use is
1009n/a * slower than reading the data because fseek flushes stdio's
1010n/a * internal buffers. See issue #8745. */
1011n/a assert(header_size <= 3*0xFFFFu);
1012n/a for (i = name_size; i < header_size; i++) {
1013n/a if (getc(fp) == EOF) {
1014n/a goto file_error;
1015n/a }
1016n/a }
1017n/a
1018n/a bootstrap = 0;
1019n/a if (flags & 0x0800) {
1020n/a charset = "utf-8";
1021n/a }
1022n/a else if (!PyThreadState_GET()->interp->codecs_initialized) {
1023n/a /* During bootstrap, we may need to load the encodings
1024n/a package from a ZIP file. But the cp437 encoding is implemented
1025n/a in Python in the encodings package.
1026n/a
1027n/a Break out of this dependency by assuming that the path to
1028n/a the encodings module is ASCII-only. */
1029n/a charset = "ascii";
1030n/a bootstrap = 1;
1031n/a }
1032n/a else {
1033n/a charset = "cp437";
1034n/a }
1035n/a nameobj = PyUnicode_Decode(name, name_size, charset, NULL);
1036n/a if (nameobj == NULL) {
1037n/a if (bootstrap) {
1038n/a PyErr_Format(PyExc_NotImplementedError,
1039n/a "bootstrap issue: python%i%i.zip contains non-ASCII "
1040n/a "filenames without the unicode flag",
1041n/a PY_MAJOR_VERSION, PY_MINOR_VERSION);
1042n/a }
1043n/a goto error;
1044n/a }
1045n/a if (PyUnicode_READY(nameobj) == -1) {
1046n/a goto error;
1047n/a }
1048n/a path = PyUnicode_FromFormat("%U%c%U", archive, SEP, nameobj);
1049n/a if (path == NULL) {
1050n/a goto error;
1051n/a }
1052n/a t = Py_BuildValue("NHIIkHHI", path, compress, data_size,
1053n/a file_size, file_offset, time, date, crc);
1054n/a if (t == NULL) {
1055n/a goto error;
1056n/a }
1057n/a err = PyDict_SetItem(files, nameobj, t);
1058n/a Py_CLEAR(nameobj);
1059n/a Py_DECREF(t);
1060n/a if (err != 0) {
1061n/a goto error;
1062n/a }
1063n/a count++;
1064n/a }
1065n/a fclose(fp);
1066n/a if (Py_VerboseFlag) {
1067n/a PySys_FormatStderr("# zipimport: found %u names in %R\n",
1068n/a count, archive);
1069n/a }
1070n/a return files;
1071n/a
1072n/aeof_error:
1073n/a set_file_error(archive, !ferror(fp));
1074n/a goto error;
1075n/a
1076n/afile_error:
1077n/a PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
1078n/a goto error;
1079n/a
1080n/ainvalid_header:
1081n/a assert(errmsg != NULL);
1082n/a PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
1083n/a goto error;
1084n/a
1085n/aerror:
1086n/a fclose(fp);
1087n/a Py_XDECREF(files);
1088n/a Py_XDECREF(nameobj);
1089n/a return NULL;
1090n/a}
1091n/a
1092n/a/* Return the zlib.decompress function object, or NULL if zlib couldn't
1093n/a be imported. The function is cached when found, so subsequent calls
1094n/a don't import zlib again. */
1095n/astatic PyObject *
1096n/aget_decompress_func(void)
1097n/a{
1098n/a static int importing_zlib = 0;
1099n/a PyObject *zlib;
1100n/a PyObject *decompress;
1101n/a _Py_IDENTIFIER(decompress);
1102n/a
1103n/a if (importing_zlib != 0)
1104n/a /* Someone has a zlib.py[co] in their Zip file;
1105n/a let's avoid a stack overflow. */
1106n/a return NULL;
1107n/a importing_zlib = 1;
1108n/a zlib = PyImport_ImportModuleNoBlock("zlib");
1109n/a importing_zlib = 0;
1110n/a if (zlib != NULL) {
1111n/a decompress = _PyObject_GetAttrId(zlib,
1112n/a &PyId_decompress);
1113n/a Py_DECREF(zlib);
1114n/a }
1115n/a else {
1116n/a PyErr_Clear();
1117n/a decompress = NULL;
1118n/a }
1119n/a if (Py_VerboseFlag)
1120n/a PySys_WriteStderr("# zipimport: zlib %s\n",
1121n/a zlib != NULL ? "available": "UNAVAILABLE");
1122n/a return decompress;
1123n/a}
1124n/a
1125n/a/* Given a path to a Zip file and a toc_entry, return the (uncompressed)
1126n/a data as a new reference. */
1127n/astatic PyObject *
1128n/aget_data(PyObject *archive, PyObject *toc_entry)
1129n/a{
1130n/a PyObject *raw_data = NULL, *data, *decompress;
1131n/a char *buf;
1132n/a FILE *fp;
1133n/a PyObject *datapath;
1134n/a unsigned short compress, time, date;
1135n/a unsigned int crc;
1136n/a Py_ssize_t data_size, file_size, bytes_size;
1137n/a long file_offset, header_size;
1138n/a unsigned char buffer[30];
1139n/a const char *errmsg = NULL;
1140n/a
1141n/a if (!PyArg_ParseTuple(toc_entry, "OHnnlHHI", &datapath, &compress,
1142n/a &data_size, &file_size, &file_offset, &time,
1143n/a &date, &crc)) {
1144n/a return NULL;
1145n/a }
1146n/a if (data_size < 0) {
1147n/a PyErr_Format(ZipImportError, "negative data size");
1148n/a return NULL;
1149n/a }
1150n/a
1151n/a fp = _Py_fopen_obj(archive, "rb");
1152n/a if (!fp) {
1153n/a return NULL;
1154n/a }
1155n/a /* Check to make sure the local file header is correct */
1156n/a if (fseek(fp, file_offset, 0) == -1) {
1157n/a goto file_error;
1158n/a }
1159n/a if (fread(buffer, 1, 30, fp) != 30) {
1160n/a goto eof_error;
1161n/a }
1162n/a if (get_uint32(buffer) != 0x04034B50u) {
1163n/a /* Bad: Local File Header */
1164n/a errmsg = "bad local file header";
1165n/a goto invalid_header;
1166n/a }
1167n/a
1168n/a header_size = (unsigned int)30 +
1169n/a get_uint16(buffer + 26) /* file name */ +
1170n/a get_uint16(buffer + 28) /* extra field */;
1171n/a if (file_offset > LONG_MAX - header_size) {
1172n/a errmsg = "bad local file header size";
1173n/a goto invalid_header;
1174n/a }
1175n/a file_offset += header_size; /* Start of file data */
1176n/a
1177n/a if (data_size > LONG_MAX - 1) {
1178n/a fclose(fp);
1179n/a PyErr_NoMemory();
1180n/a return NULL;
1181n/a }
1182n/a bytes_size = compress == 0 ? data_size : data_size + 1;
1183n/a if (bytes_size == 0) {
1184n/a bytes_size++;
1185n/a }
1186n/a raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size);
1187n/a if (raw_data == NULL) {
1188n/a goto error;
1189n/a }
1190n/a buf = PyBytes_AsString(raw_data);
1191n/a
1192n/a if (fseek(fp, file_offset, 0) == -1) {
1193n/a goto file_error;
1194n/a }
1195n/a if (fread(buf, 1, data_size, fp) != (size_t)data_size) {
1196n/a PyErr_SetString(PyExc_IOError,
1197n/a "zipimport: can't read data");
1198n/a goto error;
1199n/a }
1200n/a
1201n/a fclose(fp);
1202n/a fp = NULL;
1203n/a
1204n/a if (compress != 0) {
1205n/a buf[data_size] = 'Z'; /* saw this in zipfile.py */
1206n/a data_size++;
1207n/a }
1208n/a buf[data_size] = '\0';
1209n/a
1210n/a if (compress == 0) { /* data is not compressed */
1211n/a data = PyBytes_FromStringAndSize(buf, data_size);
1212n/a Py_DECREF(raw_data);
1213n/a return data;
1214n/a }
1215n/a
1216n/a /* Decompress with zlib */
1217n/a decompress = get_decompress_func();
1218n/a if (decompress == NULL) {
1219n/a PyErr_SetString(ZipImportError,
1220n/a "can't decompress data; "
1221n/a "zlib not available");
1222n/a goto error;
1223n/a }
1224n/a data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
1225n/a Py_DECREF(decompress);
1226n/a Py_DECREF(raw_data);
1227n/a return data;
1228n/a
1229n/aeof_error:
1230n/a set_file_error(archive, !ferror(fp));
1231n/a goto error;
1232n/a
1233n/afile_error:
1234n/a PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
1235n/a goto error;
1236n/a
1237n/ainvalid_header:
1238n/a assert(errmsg != NULL);
1239n/a PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
1240n/a goto error;
1241n/a
1242n/aerror:
1243n/a if (fp != NULL) {
1244n/a fclose(fp);
1245n/a }
1246n/a Py_XDECREF(raw_data);
1247n/a return NULL;
1248n/a}
1249n/a
1250n/a/* Lenient date/time comparison function. The precision of the mtime
1251n/a in the archive is lower than the mtime stored in a .pyc: we
1252n/a must allow a difference of at most one second. */
1253n/astatic int
1254n/aeq_mtime(time_t t1, time_t t2)
1255n/a{
1256n/a time_t d = t1 - t2;
1257n/a if (d < 0)
1258n/a d = -d;
1259n/a /* dostime only stores even seconds, so be lenient */
1260n/a return d <= 1;
1261n/a}
1262n/a
1263n/a/* Given the contents of a .py[co] file in a buffer, unmarshal the data
1264n/a and return the code object. Return None if it the magic word doesn't
1265n/a match (we do this instead of raising an exception as we fall back
1266n/a to .py if available and we don't want to mask other errors).
1267n/a Returns a new reference. */
1268n/astatic PyObject *
1269n/aunmarshal_code(PyObject *pathname, PyObject *data, time_t mtime)
1270n/a{
1271n/a PyObject *code;
1272n/a unsigned char *buf = (unsigned char *)PyBytes_AsString(data);
1273n/a Py_ssize_t size = PyBytes_Size(data);
1274n/a
1275n/a if (size < 12) {
1276n/a PyErr_SetString(ZipImportError,
1277n/a "bad pyc data");
1278n/a return NULL;
1279n/a }
1280n/a
1281n/a if (get_uint32(buf) != (unsigned int)PyImport_GetMagicNumber()) {
1282n/a if (Py_VerboseFlag) {
1283n/a PySys_FormatStderr("# %R has bad magic\n",
1284n/a pathname);
1285n/a }
1286n/a Py_RETURN_NONE; /* signal caller to try alternative */
1287n/a }
1288n/a
1289n/a if (mtime != 0 && !eq_mtime(get_uint32(buf + 4), mtime)) {
1290n/a if (Py_VerboseFlag) {
1291n/a PySys_FormatStderr("# %R has bad mtime\n",
1292n/a pathname);
1293n/a }
1294n/a Py_RETURN_NONE; /* signal caller to try alternative */
1295n/a }
1296n/a
1297n/a /* XXX the pyc's size field is ignored; timestamp collisions are probably
1298n/a unimportant with zip files. */
1299n/a code = PyMarshal_ReadObjectFromString((char *)buf + 12, size - 12);
1300n/a if (code == NULL) {
1301n/a return NULL;
1302n/a }
1303n/a if (!PyCode_Check(code)) {
1304n/a Py_DECREF(code);
1305n/a PyErr_Format(PyExc_TypeError,
1306n/a "compiled module %R is not a code object",
1307n/a pathname);
1308n/a return NULL;
1309n/a }
1310n/a return code;
1311n/a}
1312n/a
1313n/a/* Replace any occurrences of "\r\n?" in the input string with "\n".
1314n/a This converts DOS and Mac line endings to Unix line endings.
1315n/a Also append a trailing "\n" to be compatible with
1316n/a PyParser_SimpleParseFile(). Returns a new reference. */
1317n/astatic PyObject *
1318n/anormalize_line_endings(PyObject *source)
1319n/a{
1320n/a char *buf, *q, *p;
1321n/a PyObject *fixed_source;
1322n/a int len = 0;
1323n/a
1324n/a p = PyBytes_AsString(source);
1325n/a if (p == NULL) {
1326n/a return PyBytes_FromStringAndSize("\n\0", 2);
1327n/a }
1328n/a
1329n/a /* one char extra for trailing \n and one for terminating \0 */
1330n/a buf = (char *)PyMem_Malloc(PyBytes_Size(source) + 2);
1331n/a if (buf == NULL) {
1332n/a PyErr_SetString(PyExc_MemoryError,
1333n/a "zipimport: no memory to allocate "
1334n/a "source buffer");
1335n/a return NULL;
1336n/a }
1337n/a /* replace "\r\n?" by "\n" */
1338n/a for (q = buf; *p != '\0'; p++) {
1339n/a if (*p == '\r') {
1340n/a *q++ = '\n';
1341n/a if (*(p + 1) == '\n')
1342n/a p++;
1343n/a }
1344n/a else
1345n/a *q++ = *p;
1346n/a len++;
1347n/a }
1348n/a *q++ = '\n'; /* add trailing \n */
1349n/a *q = '\0';
1350n/a fixed_source = PyBytes_FromStringAndSize(buf, len + 2);
1351n/a PyMem_Free(buf);
1352n/a return fixed_source;
1353n/a}
1354n/a
1355n/a/* Given a string buffer containing Python source code, compile it
1356n/a and return a code object as a new reference. */
1357n/astatic PyObject *
1358n/acompile_source(PyObject *pathname, PyObject *source)
1359n/a{
1360n/a PyObject *code, *fixed_source;
1361n/a
1362n/a fixed_source = normalize_line_endings(source);
1363n/a if (fixed_source == NULL) {
1364n/a return NULL;
1365n/a }
1366n/a
1367n/a code = Py_CompileStringObject(PyBytes_AsString(fixed_source),
1368n/a pathname, Py_file_input, NULL, -1);
1369n/a
1370n/a Py_DECREF(fixed_source);
1371n/a return code;
1372n/a}
1373n/a
1374n/a/* Convert the date/time values found in the Zip archive to a value
1375n/a that's compatible with the time stamp stored in .pyc files. */
1376n/astatic time_t
1377n/aparse_dostime(int dostime, int dosdate)
1378n/a{
1379n/a struct tm stm;
1380n/a
1381n/a memset((void *) &stm, '\0', sizeof(stm));
1382n/a
1383n/a stm.tm_sec = (dostime & 0x1f) * 2;
1384n/a stm.tm_min = (dostime >> 5) & 0x3f;
1385n/a stm.tm_hour = (dostime >> 11) & 0x1f;
1386n/a stm.tm_mday = dosdate & 0x1f;
1387n/a stm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;
1388n/a stm.tm_year = ((dosdate >> 9) & 0x7f) + 80;
1389n/a stm.tm_isdst = -1; /* wday/yday is ignored */
1390n/a
1391n/a return mktime(&stm);
1392n/a}
1393n/a
1394n/a/* Given a path to a .pyc file in the archive, return the
1395n/a modification time of the matching .py file, or 0 if no source
1396n/a is available. */
1397n/astatic time_t
1398n/aget_mtime_of_source(ZipImporter *self, PyObject *path)
1399n/a{
1400n/a PyObject *toc_entry, *stripped;
1401n/a time_t mtime;
1402n/a
1403n/a /* strip 'c' or 'o' from *.py[co] */
1404n/a if (PyUnicode_READY(path) == -1)
1405n/a return (time_t)-1;
1406n/a stripped = PyUnicode_FromKindAndData(PyUnicode_KIND(path),
1407n/a PyUnicode_DATA(path),
1408n/a PyUnicode_GET_LENGTH(path) - 1);
1409n/a if (stripped == NULL)
1410n/a return (time_t)-1;
1411n/a
1412n/a toc_entry = PyDict_GetItem(self->files, stripped);
1413n/a Py_DECREF(stripped);
1414n/a if (toc_entry != NULL && PyTuple_Check(toc_entry) &&
1415n/a PyTuple_Size(toc_entry) == 8) {
1416n/a /* fetch the time stamp of the .py file for comparison
1417n/a with an embedded pyc time stamp */
1418n/a int time, date;
1419n/a time = PyLong_AsLong(PyTuple_GetItem(toc_entry, 5));
1420n/a date = PyLong_AsLong(PyTuple_GetItem(toc_entry, 6));
1421n/a mtime = parse_dostime(time, date);
1422n/a } else
1423n/a mtime = 0;
1424n/a return mtime;
1425n/a}
1426n/a
1427n/a/* Return the code object for the module named by 'fullname' from the
1428n/a Zip archive as a new reference. */
1429n/astatic PyObject *
1430n/aget_code_from_data(ZipImporter *self, int ispackage, int isbytecode,
1431n/a time_t mtime, PyObject *toc_entry)
1432n/a{
1433n/a PyObject *data, *modpath, *code;
1434n/a
1435n/a data = get_data(self->archive, toc_entry);
1436n/a if (data == NULL)
1437n/a return NULL;
1438n/a
1439n/a modpath = PyTuple_GetItem(toc_entry, 0);
1440n/a if (isbytecode)
1441n/a code = unmarshal_code(modpath, data, mtime);
1442n/a else
1443n/a code = compile_source(modpath, data);
1444n/a Py_DECREF(data);
1445n/a return code;
1446n/a}
1447n/a
1448n/a/* Get the code object associated with the module specified by
1449n/a 'fullname'. */
1450n/astatic PyObject *
1451n/aget_module_code(ZipImporter *self, PyObject *fullname,
1452n/a int *p_ispackage, PyObject **p_modpath)
1453n/a{
1454n/a PyObject *code = NULL, *toc_entry, *subname;
1455n/a PyObject *path, *fullpath = NULL;
1456n/a struct st_zip_searchorder *zso;
1457n/a
1458n/a subname = get_subname(fullname);
1459n/a if (subname == NULL)
1460n/a return NULL;
1461n/a
1462n/a path = make_filename(self->prefix, subname);
1463n/a Py_DECREF(subname);
1464n/a if (path == NULL)
1465n/a return NULL;
1466n/a
1467n/a for (zso = zip_searchorder; *zso->suffix; zso++) {
1468n/a code = NULL;
1469n/a
1470n/a fullpath = PyUnicode_FromFormat("%U%s", path, zso->suffix);
1471n/a if (fullpath == NULL)
1472n/a goto exit;
1473n/a
1474n/a if (Py_VerboseFlag > 1)
1475n/a PySys_FormatStderr("# trying %U%c%U\n",
1476n/a self->archive, (int)SEP, fullpath);
1477n/a toc_entry = PyDict_GetItem(self->files, fullpath);
1478n/a if (toc_entry != NULL) {
1479n/a time_t mtime = 0;
1480n/a int ispackage = zso->type & IS_PACKAGE;
1481n/a int isbytecode = zso->type & IS_BYTECODE;
1482n/a
1483n/a if (isbytecode) {
1484n/a mtime = get_mtime_of_source(self, fullpath);
1485n/a if (mtime == (time_t)-1 && PyErr_Occurred()) {
1486n/a goto exit;
1487n/a }
1488n/a }
1489n/a Py_CLEAR(fullpath);
1490n/a if (p_ispackage != NULL)
1491n/a *p_ispackage = ispackage;
1492n/a code = get_code_from_data(self, ispackage,
1493n/a isbytecode, mtime,
1494n/a toc_entry);
1495n/a if (code == Py_None) {
1496n/a /* bad magic number or non-matching mtime
1497n/a in byte code, try next */
1498n/a Py_DECREF(code);
1499n/a continue;
1500n/a }
1501n/a if (code != NULL && p_modpath != NULL) {
1502n/a *p_modpath = PyTuple_GetItem(toc_entry, 0);
1503n/a Py_INCREF(*p_modpath);
1504n/a }
1505n/a goto exit;
1506n/a }
1507n/a else
1508n/a Py_CLEAR(fullpath);
1509n/a }
1510n/a PyErr_Format(ZipImportError, "can't find module %R", fullname);
1511n/aexit:
1512n/a Py_DECREF(path);
1513n/a Py_XDECREF(fullpath);
1514n/a return code;
1515n/a}
1516n/a
1517n/a
1518n/a/* Module init */
1519n/a
1520n/aPyDoc_STRVAR(zipimport_doc,
1521n/a"zipimport provides support for importing Python modules from Zip archives.\n\
1522n/a\n\
1523n/aThis module exports three objects:\n\
1524n/a- zipimporter: a class; its constructor takes a path to a Zip archive.\n\
1525n/a- ZipImportError: exception raised by zipimporter objects. It's a\n\
1526n/a subclass of ImportError, so it can be caught as ImportError, too.\n\
1527n/a- _zip_directory_cache: a dict, mapping archive paths to zip directory\n\
1528n/a info dicts, as used in zipimporter._files.\n\
1529n/a\n\
1530n/aIt is usually not needed to use the zipimport module explicitly; it is\n\
1531n/aused by the builtin import mechanism for sys.path items that are paths\n\
1532n/ato Zip archives.");
1533n/a
1534n/astatic struct PyModuleDef zipimportmodule = {
1535n/a PyModuleDef_HEAD_INIT,
1536n/a "zipimport",
1537n/a zipimport_doc,
1538n/a -1,
1539n/a NULL,
1540n/a NULL,
1541n/a NULL,
1542n/a NULL,
1543n/a NULL
1544n/a};
1545n/a
1546n/aPyMODINIT_FUNC
1547n/aPyInit_zipimport(void)
1548n/a{
1549n/a PyObject *mod;
1550n/a
1551n/a if (PyType_Ready(&ZipImporter_Type) < 0)
1552n/a return NULL;
1553n/a
1554n/a /* Correct directory separator */
1555n/a zip_searchorder[0].suffix[0] = SEP;
1556n/a zip_searchorder[1].suffix[0] = SEP;
1557n/a
1558n/a mod = PyModule_Create(&zipimportmodule);
1559n/a if (mod == NULL)
1560n/a return NULL;
1561n/a
1562n/a ZipImportError = PyErr_NewException("zipimport.ZipImportError",
1563n/a PyExc_ImportError, NULL);
1564n/a if (ZipImportError == NULL)
1565n/a return NULL;
1566n/a
1567n/a Py_INCREF(ZipImportError);
1568n/a if (PyModule_AddObject(mod, "ZipImportError",
1569n/a ZipImportError) < 0)
1570n/a return NULL;
1571n/a
1572n/a Py_INCREF(&ZipImporter_Type);
1573n/a if (PyModule_AddObject(mod, "zipimporter",
1574n/a (PyObject *)&ZipImporter_Type) < 0)
1575n/a return NULL;
1576n/a
1577n/a zip_directory_cache = PyDict_New();
1578n/a if (zip_directory_cache == NULL)
1579n/a return NULL;
1580n/a Py_INCREF(zip_directory_cache);
1581n/a if (PyModule_AddObject(mod, "_zip_directory_cache",
1582n/a zip_directory_cache) < 0)
1583n/a return NULL;
1584n/a return mod;
1585n/a}