]>
Commit | Line | Data |
---|---|---|
7eb75bcc DM |
1 | #include "Python.h"\r |
2 | #include "structmember.h"\r | |
3 | #include "osdefs.h"\r | |
4 | #include "marshal.h"\r | |
5 | #include <time.h>\r | |
6 | \r | |
7 | \r | |
8 | #define IS_SOURCE 0x0\r | |
9 | #define IS_BYTECODE 0x1\r | |
10 | #define IS_PACKAGE 0x2\r | |
11 | \r | |
12 | struct st_zip_searchorder {\r | |
13 | char suffix[14];\r | |
14 | int type;\r | |
15 | };\r | |
16 | \r | |
17 | /* zip_searchorder defines how we search for a module in the Zip\r | |
18 | archive: we first search for a package __init__, then for\r | |
19 | non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries\r | |
20 | are swapped by initzipimport() if we run in optimized mode. Also,\r | |
21 | '/' is replaced by SEP there. */\r | |
22 | static struct st_zip_searchorder zip_searchorder[] = {\r | |
23 | {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},\r | |
24 | {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},\r | |
25 | {"/__init__.py", IS_PACKAGE | IS_SOURCE},\r | |
26 | {".pyc", IS_BYTECODE},\r | |
27 | {".pyo", IS_BYTECODE},\r | |
28 | {".py", IS_SOURCE},\r | |
29 | {"", 0}\r | |
30 | };\r | |
31 | \r | |
32 | /* zipimporter object definition and support */\r | |
33 | \r | |
34 | typedef struct _zipimporter ZipImporter;\r | |
35 | \r | |
36 | struct _zipimporter {\r | |
37 | PyObject_HEAD\r | |
38 | PyObject *archive; /* pathname of the Zip archive */\r | |
39 | PyObject *prefix; /* file prefix: "a/sub/directory/" */\r | |
40 | PyObject *files; /* dict with file info {path: toc_entry} */\r | |
41 | };\r | |
42 | \r | |
43 | static PyObject *ZipImportError;\r | |
44 | static PyObject *zip_directory_cache = NULL;\r | |
45 | \r | |
46 | /* forward decls */\r | |
47 | static PyObject *read_directory(char *archive);\r | |
48 | static PyObject *get_data(char *archive, PyObject *toc_entry);\r | |
49 | static PyObject *get_module_code(ZipImporter *self, char *fullname,\r | |
50 | int *p_ispackage, char **p_modpath);\r | |
51 | \r | |
52 | \r | |
53 | #define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type)\r | |
54 | \r | |
55 | \r | |
56 | /* zipimporter.__init__\r | |
57 | Split the "subdirectory" from the Zip archive path, lookup a matching\r | |
58 | entry in sys.path_importer_cache, fetch the file directory from there\r | |
59 | if found, or else read it from the archive. */\r | |
60 | static int\r | |
61 | zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)\r | |
62 | {\r | |
63 | char *path, *p, *prefix, buf[MAXPATHLEN+2];\r | |
64 | size_t len;\r | |
65 | \r | |
66 | if (!_PyArg_NoKeywords("zipimporter()", kwds))\r | |
67 | return -1;\r | |
68 | \r | |
69 | if (!PyArg_ParseTuple(args, "s:zipimporter",\r | |
70 | &path))\r | |
71 | return -1;\r | |
72 | \r | |
73 | len = strlen(path);\r | |
74 | if (len == 0) {\r | |
75 | PyErr_SetString(ZipImportError, "archive path is empty");\r | |
76 | return -1;\r | |
77 | }\r | |
78 | if (len >= MAXPATHLEN) {\r | |
79 | PyErr_SetString(ZipImportError,\r | |
80 | "archive path too long");\r | |
81 | return -1;\r | |
82 | }\r | |
83 | strcpy(buf, path);\r | |
84 | \r | |
85 | #ifdef ALTSEP\r | |
86 | for (p = buf; *p; p++) {\r | |
87 | if (*p == ALTSEP)\r | |
88 | *p = SEP;\r | |
89 | }\r | |
90 | #endif\r | |
91 | \r | |
92 | path = NULL;\r | |
93 | prefix = NULL;\r | |
94 | for (;;) {\r | |
95 | #ifndef RISCOS\r | |
96 | struct stat statbuf;\r | |
97 | int rv;\r | |
98 | \r | |
99 | rv = stat(buf, &statbuf);\r | |
100 | if (rv == 0) {\r | |
101 | /* it exists */\r | |
102 | if (S_ISREG(statbuf.st_mode))\r | |
103 | /* it's a file */\r | |
104 | path = buf;\r | |
105 | break;\r | |
106 | }\r | |
107 | #else\r | |
108 | if (object_exists(buf)) {\r | |
109 | /* it exists */\r | |
110 | if (isfile(buf))\r | |
111 | /* it's a file */\r | |
112 | path = buf;\r | |
113 | break;\r | |
114 | }\r | |
115 | #endif\r | |
116 | /* back up one path element */\r | |
117 | p = strrchr(buf, SEP);\r | |
118 | if (prefix != NULL)\r | |
119 | *prefix = SEP;\r | |
120 | if (p == NULL)\r | |
121 | break;\r | |
122 | *p = '\0';\r | |
123 | prefix = p;\r | |
124 | }\r | |
125 | if (path != NULL) {\r | |
126 | PyObject *files;\r | |
127 | files = PyDict_GetItemString(zip_directory_cache, path);\r | |
128 | if (files == NULL) {\r | |
129 | files = read_directory(buf);\r | |
130 | if (files == NULL)\r | |
131 | return -1;\r | |
132 | if (PyDict_SetItemString(zip_directory_cache, path,\r | |
133 | files) != 0)\r | |
134 | return -1;\r | |
135 | }\r | |
136 | else\r | |
137 | Py_INCREF(files);\r | |
138 | self->files = files;\r | |
139 | }\r | |
140 | else {\r | |
141 | PyErr_SetString(ZipImportError, "not a Zip file");\r | |
142 | return -1;\r | |
143 | }\r | |
144 | \r | |
145 | if (prefix == NULL)\r | |
146 | prefix = "";\r | |
147 | else {\r | |
148 | prefix++;\r | |
149 | len = strlen(prefix);\r | |
150 | if (prefix[len-1] != SEP) {\r | |
151 | /* add trailing SEP */\r | |
152 | prefix[len] = SEP;\r | |
153 | prefix[len + 1] = '\0';\r | |
154 | }\r | |
155 | }\r | |
156 | \r | |
157 | self->archive = PyString_FromString(buf);\r | |
158 | if (self->archive == NULL)\r | |
159 | return -1;\r | |
160 | \r | |
161 | self->prefix = PyString_FromString(prefix);\r | |
162 | if (self->prefix == NULL)\r | |
163 | return -1;\r | |
164 | \r | |
165 | return 0;\r | |
166 | }\r | |
167 | \r | |
168 | /* GC support. */\r | |
169 | static int\r | |
170 | zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)\r | |
171 | {\r | |
172 | ZipImporter *self = (ZipImporter *)obj;\r | |
173 | Py_VISIT(self->files);\r | |
174 | return 0;\r | |
175 | }\r | |
176 | \r | |
177 | static void\r | |
178 | zipimporter_dealloc(ZipImporter *self)\r | |
179 | {\r | |
180 | PyObject_GC_UnTrack(self);\r | |
181 | Py_XDECREF(self->archive);\r | |
182 | Py_XDECREF(self->prefix);\r | |
183 | Py_XDECREF(self->files);\r | |
184 | Py_TYPE(self)->tp_free((PyObject *)self);\r | |
185 | }\r | |
186 | \r | |
187 | static PyObject *\r | |
188 | zipimporter_repr(ZipImporter *self)\r | |
189 | {\r | |
190 | char buf[500];\r | |
191 | char *archive = "???";\r | |
192 | char *prefix = "";\r | |
193 | \r | |
194 | if (self->archive != NULL && PyString_Check(self->archive))\r | |
195 | archive = PyString_AsString(self->archive);\r | |
196 | if (self->prefix != NULL && PyString_Check(self->prefix))\r | |
197 | prefix = PyString_AsString(self->prefix);\r | |
198 | if (prefix != NULL && *prefix)\r | |
199 | PyOS_snprintf(buf, sizeof(buf),\r | |
200 | "<zipimporter object \"%.300s%c%.150s\">",\r | |
201 | archive, SEP, prefix);\r | |
202 | else\r | |
203 | PyOS_snprintf(buf, sizeof(buf),\r | |
204 | "<zipimporter object \"%.300s\">",\r | |
205 | archive);\r | |
206 | return PyString_FromString(buf);\r | |
207 | }\r | |
208 | \r | |
209 | /* return fullname.split(".")[-1] */\r | |
210 | static char *\r | |
211 | get_subname(char *fullname)\r | |
212 | {\r | |
213 | char *subname = strrchr(fullname, '.');\r | |
214 | if (subname == NULL)\r | |
215 | subname = fullname;\r | |
216 | else\r | |
217 | subname++;\r | |
218 | return subname;\r | |
219 | }\r | |
220 | \r | |
221 | /* Given a (sub)modulename, write the potential file path in the\r | |
222 | archive (without extension) to the path buffer. Return the\r | |
223 | length of the resulting string. */\r | |
224 | static int\r | |
225 | make_filename(char *prefix, char *name, char *path)\r | |
226 | {\r | |
227 | size_t len;\r | |
228 | char *p;\r | |
229 | \r | |
230 | len = strlen(prefix);\r | |
231 | \r | |
232 | /* self.prefix + name [+ SEP + "__init__"] + ".py[co]" */\r | |
233 | if (len + strlen(name) + 13 >= MAXPATHLEN) {\r | |
234 | PyErr_SetString(ZipImportError, "path too long");\r | |
235 | return -1;\r | |
236 | }\r | |
237 | \r | |
238 | strcpy(path, prefix);\r | |
239 | strcpy(path + len, name);\r | |
240 | for (p = path + len; *p; p++) {\r | |
241 | if (*p == '.')\r | |
242 | *p = SEP;\r | |
243 | }\r | |
244 | len += strlen(name);\r | |
245 | assert(len < INT_MAX);\r | |
246 | return (int)len;\r | |
247 | }\r | |
248 | \r | |
249 | enum zi_module_info {\r | |
250 | MI_ERROR,\r | |
251 | MI_NOT_FOUND,\r | |
252 | MI_MODULE,\r | |
253 | MI_PACKAGE\r | |
254 | };\r | |
255 | \r | |
256 | /* Return some information about a module. */\r | |
257 | static enum zi_module_info\r | |
258 | get_module_info(ZipImporter *self, char *fullname)\r | |
259 | {\r | |
260 | char *subname, path[MAXPATHLEN + 1];\r | |
261 | int len;\r | |
262 | struct st_zip_searchorder *zso;\r | |
263 | \r | |
264 | subname = get_subname(fullname);\r | |
265 | \r | |
266 | len = make_filename(PyString_AsString(self->prefix), subname, path);\r | |
267 | if (len < 0)\r | |
268 | return MI_ERROR;\r | |
269 | \r | |
270 | for (zso = zip_searchorder; *zso->suffix; zso++) {\r | |
271 | strcpy(path + len, zso->suffix);\r | |
272 | if (PyDict_GetItemString(self->files, path) != NULL) {\r | |
273 | if (zso->type & IS_PACKAGE)\r | |
274 | return MI_PACKAGE;\r | |
275 | else\r | |
276 | return MI_MODULE;\r | |
277 | }\r | |
278 | }\r | |
279 | return MI_NOT_FOUND;\r | |
280 | }\r | |
281 | \r | |
282 | /* Check whether we can satisfy the import of the module named by\r | |
283 | 'fullname'. Return self if we can, None if we can't. */\r | |
284 | static PyObject *\r | |
285 | zipimporter_find_module(PyObject *obj, PyObject *args)\r | |
286 | {\r | |
287 | ZipImporter *self = (ZipImporter *)obj;\r | |
288 | PyObject *path = NULL;\r | |
289 | char *fullname;\r | |
290 | enum zi_module_info mi;\r | |
291 | \r | |
292 | if (!PyArg_ParseTuple(args, "s|O:zipimporter.find_module",\r | |
293 | &fullname, &path))\r | |
294 | return NULL;\r | |
295 | \r | |
296 | mi = get_module_info(self, fullname);\r | |
297 | if (mi == MI_ERROR)\r | |
298 | return NULL;\r | |
299 | if (mi == MI_NOT_FOUND) {\r | |
300 | Py_INCREF(Py_None);\r | |
301 | return Py_None;\r | |
302 | }\r | |
303 | Py_INCREF(self);\r | |
304 | return (PyObject *)self;\r | |
305 | }\r | |
306 | \r | |
307 | /* Load and return the module named by 'fullname'. */\r | |
308 | static PyObject *\r | |
309 | zipimporter_load_module(PyObject *obj, PyObject *args)\r | |
310 | {\r | |
311 | ZipImporter *self = (ZipImporter *)obj;\r | |
312 | PyObject *code, *mod, *dict;\r | |
313 | char *fullname, *modpath;\r | |
314 | int ispackage;\r | |
315 | \r | |
316 | if (!PyArg_ParseTuple(args, "s:zipimporter.load_module",\r | |
317 | &fullname))\r | |
318 | return NULL;\r | |
319 | \r | |
320 | code = get_module_code(self, fullname, &ispackage, &modpath);\r | |
321 | if (code == NULL)\r | |
322 | return NULL;\r | |
323 | \r | |
324 | mod = PyImport_AddModule(fullname);\r | |
325 | if (mod == NULL) {\r | |
326 | Py_DECREF(code);\r | |
327 | return NULL;\r | |
328 | }\r | |
329 | dict = PyModule_GetDict(mod);\r | |
330 | \r | |
331 | /* mod.__loader__ = self */\r | |
332 | if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)\r | |
333 | goto error;\r | |
334 | \r | |
335 | if (ispackage) {\r | |
336 | /* add __path__ to the module *before* the code gets\r | |
337 | executed */\r | |
338 | PyObject *pkgpath, *fullpath;\r | |
339 | char *prefix = PyString_AsString(self->prefix);\r | |
340 | char *subname = get_subname(fullname);\r | |
341 | int err;\r | |
342 | \r | |
343 | fullpath = PyString_FromFormat("%s%c%s%s",\r | |
344 | PyString_AsString(self->archive),\r | |
345 | SEP,\r | |
346 | *prefix ? prefix : "",\r | |
347 | subname);\r | |
348 | if (fullpath == NULL)\r | |
349 | goto error;\r | |
350 | \r | |
351 | pkgpath = Py_BuildValue("[O]", fullpath);\r | |
352 | Py_DECREF(fullpath);\r | |
353 | if (pkgpath == NULL)\r | |
354 | goto error;\r | |
355 | err = PyDict_SetItemString(dict, "__path__", pkgpath);\r | |
356 | Py_DECREF(pkgpath);\r | |
357 | if (err != 0)\r | |
358 | goto error;\r | |
359 | }\r | |
360 | mod = PyImport_ExecCodeModuleEx(fullname, code, modpath);\r | |
361 | Py_DECREF(code);\r | |
362 | if (Py_VerboseFlag)\r | |
363 | PySys_WriteStderr("import %s # loaded from Zip %s\n",\r | |
364 | fullname, modpath);\r | |
365 | return mod;\r | |
366 | error:\r | |
367 | Py_DECREF(code);\r | |
368 | Py_DECREF(mod);\r | |
369 | return NULL;\r | |
370 | }\r | |
371 | \r | |
372 | /* Return a string matching __file__ for the named module */\r | |
373 | static PyObject *\r | |
374 | zipimporter_get_filename(PyObject *obj, PyObject *args)\r | |
375 | {\r | |
376 | ZipImporter *self = (ZipImporter *)obj;\r | |
377 | PyObject *code;\r | |
378 | char *fullname, *modpath;\r | |
379 | int ispackage;\r | |
380 | \r | |
381 | if (!PyArg_ParseTuple(args, "s:zipimporter.get_filename",\r | |
382 | &fullname))\r | |
383 | return NULL;\r | |
384 | \r | |
385 | /* Deciding the filename requires working out where the code\r | |
386 | would come from if the module was actually loaded */\r | |
387 | code = get_module_code(self, fullname, &ispackage, &modpath);\r | |
388 | if (code == NULL)\r | |
389 | return NULL;\r | |
390 | Py_DECREF(code); /* Only need the path info */\r | |
391 | \r | |
392 | return PyString_FromString(modpath);\r | |
393 | }\r | |
394 | \r | |
395 | /* Return a bool signifying whether the module is a package or not. */\r | |
396 | static PyObject *\r | |
397 | zipimporter_is_package(PyObject *obj, PyObject *args)\r | |
398 | {\r | |
399 | ZipImporter *self = (ZipImporter *)obj;\r | |
400 | char *fullname;\r | |
401 | enum zi_module_info mi;\r | |
402 | \r | |
403 | if (!PyArg_ParseTuple(args, "s:zipimporter.is_package",\r | |
404 | &fullname))\r | |
405 | return NULL;\r | |
406 | \r | |
407 | mi = get_module_info(self, fullname);\r | |
408 | if (mi == MI_ERROR)\r | |
409 | return NULL;\r | |
410 | if (mi == MI_NOT_FOUND) {\r | |
411 | PyErr_Format(ZipImportError, "can't find module '%.200s'",\r | |
412 | fullname);\r | |
413 | return NULL;\r | |
414 | }\r | |
415 | return PyBool_FromLong(mi == MI_PACKAGE);\r | |
416 | }\r | |
417 | \r | |
418 | static PyObject *\r | |
419 | zipimporter_get_data(PyObject *obj, PyObject *args)\r | |
420 | {\r | |
421 | ZipImporter *self = (ZipImporter *)obj;\r | |
422 | char *path;\r | |
423 | #ifdef ALTSEP\r | |
424 | char *p, buf[MAXPATHLEN + 1];\r | |
425 | #endif\r | |
426 | PyObject *toc_entry;\r | |
427 | Py_ssize_t len;\r | |
428 | \r | |
429 | if (!PyArg_ParseTuple(args, "s:zipimporter.get_data", &path))\r | |
430 | return NULL;\r | |
431 | \r | |
432 | #ifdef ALTSEP\r | |
433 | if (strlen(path) >= MAXPATHLEN) {\r | |
434 | PyErr_SetString(ZipImportError, "path too long");\r | |
435 | return NULL;\r | |
436 | }\r | |
437 | strcpy(buf, path);\r | |
438 | for (p = buf; *p; p++) {\r | |
439 | if (*p == ALTSEP)\r | |
440 | *p = SEP;\r | |
441 | }\r | |
442 | path = buf;\r | |
443 | #endif\r | |
444 | len = PyString_Size(self->archive);\r | |
445 | if ((size_t)len < strlen(path) &&\r | |
446 | strncmp(path, PyString_AsString(self->archive), len) == 0 &&\r | |
447 | path[len] == SEP) {\r | |
448 | path = path + len + 1;\r | |
449 | }\r | |
450 | \r | |
451 | toc_entry = PyDict_GetItemString(self->files, path);\r | |
452 | if (toc_entry == NULL) {\r | |
453 | PyErr_SetFromErrnoWithFilename(PyExc_IOError, path);\r | |
454 | return NULL;\r | |
455 | }\r | |
456 | return get_data(PyString_AsString(self->archive), toc_entry);\r | |
457 | }\r | |
458 | \r | |
459 | static PyObject *\r | |
460 | zipimporter_get_code(PyObject *obj, PyObject *args)\r | |
461 | {\r | |
462 | ZipImporter *self = (ZipImporter *)obj;\r | |
463 | char *fullname;\r | |
464 | \r | |
465 | if (!PyArg_ParseTuple(args, "s:zipimporter.get_code", &fullname))\r | |
466 | return NULL;\r | |
467 | \r | |
468 | return get_module_code(self, fullname, NULL, NULL);\r | |
469 | }\r | |
470 | \r | |
471 | static PyObject *\r | |
472 | zipimporter_get_source(PyObject *obj, PyObject *args)\r | |
473 | {\r | |
474 | ZipImporter *self = (ZipImporter *)obj;\r | |
475 | PyObject *toc_entry;\r | |
476 | char *fullname, *subname, path[MAXPATHLEN+1];\r | |
477 | int len;\r | |
478 | enum zi_module_info mi;\r | |
479 | \r | |
480 | if (!PyArg_ParseTuple(args, "s:zipimporter.get_source", &fullname))\r | |
481 | return NULL;\r | |
482 | \r | |
483 | mi = get_module_info(self, fullname);\r | |
484 | if (mi == MI_ERROR)\r | |
485 | return NULL;\r | |
486 | if (mi == MI_NOT_FOUND) {\r | |
487 | PyErr_Format(ZipImportError, "can't find module '%.200s'",\r | |
488 | fullname);\r | |
489 | return NULL;\r | |
490 | }\r | |
491 | subname = get_subname(fullname);\r | |
492 | \r | |
493 | len = make_filename(PyString_AsString(self->prefix), subname, path);\r | |
494 | if (len < 0)\r | |
495 | return NULL;\r | |
496 | \r | |
497 | if (mi == MI_PACKAGE) {\r | |
498 | path[len] = SEP;\r | |
499 | strcpy(path + len + 1, "__init__.py");\r | |
500 | }\r | |
501 | else\r | |
502 | strcpy(path + len, ".py");\r | |
503 | \r | |
504 | toc_entry = PyDict_GetItemString(self->files, path);\r | |
505 | if (toc_entry != NULL)\r | |
506 | return get_data(PyString_AsString(self->archive), toc_entry);\r | |
507 | \r | |
508 | /* we have the module, but no source */\r | |
509 | Py_INCREF(Py_None);\r | |
510 | return Py_None;\r | |
511 | }\r | |
512 | \r | |
513 | PyDoc_STRVAR(doc_find_module,\r | |
514 | "find_module(fullname, path=None) -> self or None.\n\\r | |
515 | \n\\r | |
516 | Search for a module specified by 'fullname'. 'fullname' must be the\n\\r | |
517 | fully qualified (dotted) module name. It returns the zipimporter\n\\r | |
518 | instance itself if the module was found, or None if it wasn't.\n\\r | |
519 | The optional 'path' argument is ignored -- it's there for compatibility\n\\r | |
520 | with the importer protocol.");\r | |
521 | \r | |
522 | PyDoc_STRVAR(doc_load_module,\r | |
523 | "load_module(fullname) -> module.\n\\r | |
524 | \n\\r | |
525 | Load the module specified by 'fullname'. 'fullname' must be the\n\\r | |
526 | fully qualified (dotted) module name. It returns the imported\n\\r | |
527 | module, or raises ZipImportError if it wasn't found.");\r | |
528 | \r | |
529 | PyDoc_STRVAR(doc_get_data,\r | |
530 | "get_data(pathname) -> string with file data.\n\\r | |
531 | \n\\r | |
532 | Return the data associated with 'pathname'. Raise IOError if\n\\r | |
533 | the file wasn't found.");\r | |
534 | \r | |
535 | PyDoc_STRVAR(doc_is_package,\r | |
536 | "is_package(fullname) -> bool.\n\\r | |
537 | \n\\r | |
538 | Return True if the module specified by fullname is a package.\n\\r | |
539 | Raise ZipImportError if the module couldn't be found.");\r | |
540 | \r | |
541 | PyDoc_STRVAR(doc_get_code,\r | |
542 | "get_code(fullname) -> code object.\n\\r | |
543 | \n\\r | |
544 | Return the code object for the specified module. Raise ZipImportError\n\\r | |
545 | if the module couldn't be found.");\r | |
546 | \r | |
547 | PyDoc_STRVAR(doc_get_source,\r | |
548 | "get_source(fullname) -> source string.\n\\r | |
549 | \n\\r | |
550 | Return the source code for the specified module. Raise ZipImportError\n\\r | |
551 | if the module couldn't be found, return None if the archive does\n\\r | |
552 | contain the module, but has no source for it.");\r | |
553 | \r | |
554 | \r | |
555 | PyDoc_STRVAR(doc_get_filename,\r | |
556 | "get_filename(fullname) -> filename string.\n\\r | |
557 | \n\\r | |
558 | Return the filename for the specified module.");\r | |
559 | \r | |
560 | static PyMethodDef zipimporter_methods[] = {\r | |
561 | {"find_module", zipimporter_find_module, METH_VARARGS,\r | |
562 | doc_find_module},\r | |
563 | {"load_module", zipimporter_load_module, METH_VARARGS,\r | |
564 | doc_load_module},\r | |
565 | {"get_data", zipimporter_get_data, METH_VARARGS,\r | |
566 | doc_get_data},\r | |
567 | {"get_code", zipimporter_get_code, METH_VARARGS,\r | |
568 | doc_get_code},\r | |
569 | {"get_source", zipimporter_get_source, METH_VARARGS,\r | |
570 | doc_get_source},\r | |
571 | {"get_filename", zipimporter_get_filename, METH_VARARGS,\r | |
572 | doc_get_filename},\r | |
573 | {"is_package", zipimporter_is_package, METH_VARARGS,\r | |
574 | doc_is_package},\r | |
575 | {NULL, NULL} /* sentinel */\r | |
576 | };\r | |
577 | \r | |
578 | static PyMemberDef zipimporter_members[] = {\r | |
579 | {"archive", T_OBJECT, offsetof(ZipImporter, archive), READONLY},\r | |
580 | {"prefix", T_OBJECT, offsetof(ZipImporter, prefix), READONLY},\r | |
581 | {"_files", T_OBJECT, offsetof(ZipImporter, files), READONLY},\r | |
582 | {NULL}\r | |
583 | };\r | |
584 | \r | |
585 | PyDoc_STRVAR(zipimporter_doc,\r | |
586 | "zipimporter(archivepath) -> zipimporter object\n\\r | |
587 | \n\\r | |
588 | Create a new zipimporter instance. 'archivepath' must be a path to\n\\r | |
589 | a zipfile, or to a specific path inside a zipfile. For example, it can be\n\\r | |
590 | '/tmp/myimport.zip', or '/tmp/myimport.zip/mydirectory', if mydirectory is a\n\\r | |
591 | valid directory inside the archive.\n\\r | |
592 | \n\\r | |
593 | 'ZipImportError is raised if 'archivepath' doesn't point to a valid Zip\n\\r | |
594 | archive.\n\\r | |
595 | \n\\r | |
596 | The 'archive' attribute of zipimporter objects contains the name of the\n\\r | |
597 | zipfile targeted.");\r | |
598 | \r | |
599 | #define DEFERRED_ADDRESS(ADDR) 0\r | |
600 | \r | |
601 | static PyTypeObject ZipImporter_Type = {\r | |
602 | PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)\r | |
603 | "zipimport.zipimporter",\r | |
604 | sizeof(ZipImporter),\r | |
605 | 0, /* tp_itemsize */\r | |
606 | (destructor)zipimporter_dealloc, /* tp_dealloc */\r | |
607 | 0, /* tp_print */\r | |
608 | 0, /* tp_getattr */\r | |
609 | 0, /* tp_setattr */\r | |
610 | 0, /* tp_compare */\r | |
611 | (reprfunc)zipimporter_repr, /* tp_repr */\r | |
612 | 0, /* tp_as_number */\r | |
613 | 0, /* tp_as_sequence */\r | |
614 | 0, /* tp_as_mapping */\r | |
615 | 0, /* tp_hash */\r | |
616 | 0, /* tp_call */\r | |
617 | 0, /* tp_str */\r | |
618 | PyObject_GenericGetAttr, /* tp_getattro */\r | |
619 | 0, /* tp_setattro */\r | |
620 | 0, /* tp_as_buffer */\r | |
621 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |\r | |
622 | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r | |
623 | zipimporter_doc, /* tp_doc */\r | |
624 | zipimporter_traverse, /* tp_traverse */\r | |
625 | 0, /* tp_clear */\r | |
626 | 0, /* tp_richcompare */\r | |
627 | 0, /* tp_weaklistoffset */\r | |
628 | 0, /* tp_iter */\r | |
629 | 0, /* tp_iternext */\r | |
630 | zipimporter_methods, /* tp_methods */\r | |
631 | zipimporter_members, /* tp_members */\r | |
632 | 0, /* tp_getset */\r | |
633 | 0, /* tp_base */\r | |
634 | 0, /* tp_dict */\r | |
635 | 0, /* tp_descr_get */\r | |
636 | 0, /* tp_descr_set */\r | |
637 | 0, /* tp_dictoffset */\r | |
638 | (initproc)zipimporter_init, /* tp_init */\r | |
639 | PyType_GenericAlloc, /* tp_alloc */\r | |
640 | PyType_GenericNew, /* tp_new */\r | |
641 | PyObject_GC_Del, /* tp_free */\r | |
642 | };\r | |
643 | \r | |
644 | \r | |
645 | /* implementation */\r | |
646 | \r | |
647 | /* Given a buffer, return the long that is represented by the first\r | |
648 | 4 bytes, encoded as little endian. This partially reimplements\r | |
649 | marshal.c:r_long() */\r | |
650 | static long\r | |
651 | get_long(unsigned char *buf) {\r | |
652 | long x;\r | |
653 | x = buf[0];\r | |
654 | x |= (long)buf[1] << 8;\r | |
655 | x |= (long)buf[2] << 16;\r | |
656 | x |= (long)buf[3] << 24;\r | |
657 | #if SIZEOF_LONG > 4\r | |
658 | /* Sign extension for 64-bit machines */\r | |
659 | x |= -(x & 0x80000000L);\r | |
660 | #endif\r | |
661 | return x;\r | |
662 | }\r | |
663 | \r | |
664 | /*\r | |
665 | read_directory(archive) -> files dict (new reference)\r | |
666 | \r | |
667 | Given a path to a Zip archive, build a dict, mapping file names\r | |
668 | (local to the archive, using SEP as a separator) to toc entries.\r | |
669 | \r | |
670 | A toc_entry is a tuple:\r | |
671 | \r | |
672 | (__file__, # value to use for __file__, available for all files\r | |
673 | compress, # compression kind; 0 for uncompressed\r | |
674 | data_size, # size of compressed data on disk\r | |
675 | file_size, # size of decompressed data\r | |
676 | file_offset, # offset of file header from start of archive\r | |
677 | time, # mod time of file (in dos format)\r | |
678 | date, # mod data of file (in dos format)\r | |
679 | crc, # crc checksum of the data\r | |
680 | )\r | |
681 | \r | |
682 | Directories can be recognized by the trailing SEP in the name,\r | |
683 | data_size and file_offset are 0.\r | |
684 | */\r | |
685 | static PyObject *\r | |
686 | read_directory(char *archive)\r | |
687 | {\r | |
688 | PyObject *files = NULL;\r | |
689 | FILE *fp;\r | |
690 | long compress, crc, data_size, file_size, file_offset, date, time;\r | |
691 | long header_offset, name_size, header_size, header_position;\r | |
692 | long i, l, count;\r | |
693 | size_t length;\r | |
694 | char path[MAXPATHLEN + 5];\r | |
695 | char name[MAXPATHLEN + 5];\r | |
696 | char *p, endof_central_dir[22];\r | |
697 | long arc_offset; /* offset from beginning of file to start of zip-archive */\r | |
698 | \r | |
699 | if (strlen(archive) > MAXPATHLEN) {\r | |
700 | PyErr_SetString(PyExc_OverflowError,\r | |
701 | "Zip path name is too long");\r | |
702 | return NULL;\r | |
703 | }\r | |
704 | strcpy(path, archive);\r | |
705 | \r | |
706 | fp = fopen(archive, "rb");\r | |
707 | if (fp == NULL) {\r | |
708 | PyErr_Format(ZipImportError, "can't open Zip file: "\r | |
709 | "'%.200s'", archive);\r | |
710 | return NULL;\r | |
711 | }\r | |
712 | \r | |
713 | if (fseek(fp, -22, SEEK_END) == -1) {\r | |
714 | fclose(fp);\r | |
715 | PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);\r | |
716 | return NULL;\r | |
717 | }\r | |
718 | header_position = ftell(fp);\r | |
719 | if (fread(endof_central_dir, 1, 22, fp) != 22) {\r | |
720 | fclose(fp);\r | |
721 | PyErr_Format(ZipImportError, "can't read Zip file: "\r | |
722 | "'%.200s'", archive);\r | |
723 | return NULL;\r | |
724 | }\r | |
725 | if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {\r | |
726 | /* Bad: End of Central Dir signature */\r | |
727 | fclose(fp);\r | |
728 | PyErr_Format(ZipImportError, "not a Zip file: "\r | |
729 | "'%.200s'", archive);\r | |
730 | return NULL;\r | |
731 | }\r | |
732 | \r | |
733 | header_size = get_long((unsigned char *)endof_central_dir + 12);\r | |
734 | header_offset = get_long((unsigned char *)endof_central_dir + 16);\r | |
735 | arc_offset = header_position - header_offset - header_size;\r | |
736 | header_offset += arc_offset;\r | |
737 | \r | |
738 | files = PyDict_New();\r | |
739 | if (files == NULL)\r | |
740 | goto error;\r | |
741 | \r | |
742 | length = (long)strlen(path);\r | |
743 | path[length] = SEP;\r | |
744 | \r | |
745 | /* Start of Central Directory */\r | |
746 | count = 0;\r | |
747 | for (;;) {\r | |
748 | PyObject *t;\r | |
749 | int err;\r | |
750 | \r | |
751 | if (fseek(fp, header_offset, 0) == -1) /* Start of file header */\r | |
752 | goto fseek_error;\r | |
753 | l = PyMarshal_ReadLongFromFile(fp);\r | |
754 | if (l != 0x02014B50)\r | |
755 | break; /* Bad: Central Dir File Header */\r | |
756 | if (fseek(fp, header_offset + 10, 0) == -1)\r | |
757 | goto fseek_error;\r | |
758 | compress = PyMarshal_ReadShortFromFile(fp);\r | |
759 | time = PyMarshal_ReadShortFromFile(fp);\r | |
760 | date = PyMarshal_ReadShortFromFile(fp);\r | |
761 | crc = PyMarshal_ReadLongFromFile(fp);\r | |
762 | data_size = PyMarshal_ReadLongFromFile(fp);\r | |
763 | file_size = PyMarshal_ReadLongFromFile(fp);\r | |
764 | name_size = PyMarshal_ReadShortFromFile(fp);\r | |
765 | header_size = 46 + name_size +\r | |
766 | PyMarshal_ReadShortFromFile(fp) +\r | |
767 | PyMarshal_ReadShortFromFile(fp);\r | |
768 | if (fseek(fp, header_offset + 42, 0) == -1)\r | |
769 | goto fseek_error;\r | |
770 | file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;\r | |
771 | if (name_size > MAXPATHLEN)\r | |
772 | name_size = MAXPATHLEN;\r | |
773 | \r | |
774 | p = name;\r | |
775 | for (i = 0; i < name_size; i++) {\r | |
776 | *p = (char)getc(fp);\r | |
777 | if (*p == '/')\r | |
778 | *p = SEP;\r | |
779 | p++;\r | |
780 | }\r | |
781 | *p = 0; /* Add terminating null byte */\r | |
782 | header_offset += header_size;\r | |
783 | \r | |
784 | strncpy(path + length + 1, name, MAXPATHLEN - length - 1);\r | |
785 | \r | |
786 | t = Py_BuildValue("siiiiiii", path, compress, data_size,\r | |
787 | file_size, file_offset, time, date, crc);\r | |
788 | if (t == NULL)\r | |
789 | goto error;\r | |
790 | err = PyDict_SetItemString(files, name, t);\r | |
791 | Py_DECREF(t);\r | |
792 | if (err != 0)\r | |
793 | goto error;\r | |
794 | count++;\r | |
795 | }\r | |
796 | fclose(fp);\r | |
797 | if (Py_VerboseFlag)\r | |
798 | PySys_WriteStderr("# zipimport: found %ld names in %s\n",\r | |
799 | count, archive);\r | |
800 | return files;\r | |
801 | fseek_error:\r | |
802 | fclose(fp);\r | |
803 | Py_XDECREF(files);\r | |
804 | PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);\r | |
805 | return NULL;\r | |
806 | error:\r | |
807 | fclose(fp);\r | |
808 | Py_XDECREF(files);\r | |
809 | return NULL;\r | |
810 | }\r | |
811 | \r | |
812 | /* Return the zlib.decompress function object, or NULL if zlib couldn't\r | |
813 | be imported. The function is cached when found, so subsequent calls\r | |
814 | don't import zlib again. */\r | |
815 | static PyObject *\r | |
816 | get_decompress_func(void)\r | |
817 | {\r | |
818 | static int importing_zlib = 0;\r | |
819 | PyObject *zlib;\r | |
820 | PyObject *decompress;\r | |
821 | \r | |
822 | if (importing_zlib != 0)\r | |
823 | /* Someone has a zlib.py[co] in their Zip file;\r | |
824 | let's avoid a stack overflow. */\r | |
825 | return NULL;\r | |
826 | importing_zlib = 1;\r | |
827 | zlib = PyImport_ImportModuleNoBlock("zlib");\r | |
828 | importing_zlib = 0;\r | |
829 | if (zlib != NULL) {\r | |
830 | decompress = PyObject_GetAttrString(zlib,\r | |
831 | "decompress");\r | |
832 | Py_DECREF(zlib);\r | |
833 | }\r | |
834 | else {\r | |
835 | PyErr_Clear();\r | |
836 | decompress = NULL;\r | |
837 | }\r | |
838 | if (Py_VerboseFlag)\r | |
839 | PySys_WriteStderr("# zipimport: zlib %s\n",\r | |
840 | zlib != NULL ? "available": "UNAVAILABLE");\r | |
841 | return decompress;\r | |
842 | }\r | |
843 | \r | |
844 | /* Given a path to a Zip file and a toc_entry, return the (uncompressed)\r | |
845 | data as a new reference. */\r | |
846 | static PyObject *\r | |
847 | get_data(char *archive, PyObject *toc_entry)\r | |
848 | {\r | |
849 | PyObject *raw_data, *data = NULL, *decompress;\r | |
850 | char *buf;\r | |
851 | FILE *fp;\r | |
852 | int err;\r | |
853 | Py_ssize_t bytes_read = 0;\r | |
854 | long l;\r | |
855 | char *datapath;\r | |
856 | long compress, data_size, file_size, file_offset;\r | |
857 | long time, date, crc;\r | |
858 | \r | |
859 | if (!PyArg_ParseTuple(toc_entry, "slllllll", &datapath, &compress,\r | |
860 | &data_size, &file_size, &file_offset, &time,\r | |
861 | &date, &crc)) {\r | |
862 | return NULL;\r | |
863 | }\r | |
864 | \r | |
865 | fp = fopen(archive, "rb");\r | |
866 | if (!fp) {\r | |
867 | PyErr_Format(PyExc_IOError,\r | |
868 | "zipimport: can not open file %s", archive);\r | |
869 | return NULL;\r | |
870 | }\r | |
871 | \r | |
872 | /* Check to make sure the local file header is correct */\r | |
873 | if (fseek(fp, file_offset, 0) == -1) {\r | |
874 | fclose(fp);\r | |
875 | PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);\r | |
876 | return NULL;\r | |
877 | }\r | |
878 | \r | |
879 | l = PyMarshal_ReadLongFromFile(fp);\r | |
880 | if (l != 0x04034B50) {\r | |
881 | /* Bad: Local File Header */\r | |
882 | PyErr_Format(ZipImportError,\r | |
883 | "bad local file header in %s",\r | |
884 | archive);\r | |
885 | fclose(fp);\r | |
886 | return NULL;\r | |
887 | }\r | |
888 | if (fseek(fp, file_offset + 26, 0) == -1) {\r | |
889 | fclose(fp);\r | |
890 | PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);\r | |
891 | return NULL;\r | |
892 | }\r | |
893 | \r | |
894 | l = 30 + PyMarshal_ReadShortFromFile(fp) +\r | |
895 | PyMarshal_ReadShortFromFile(fp); /* local header size */\r | |
896 | file_offset += l; /* Start of file data */\r | |
897 | \r | |
898 | raw_data = PyString_FromStringAndSize((char *)NULL, compress == 0 ?\r | |
899 | data_size : data_size + 1);\r | |
900 | if (raw_data == NULL) {\r | |
901 | fclose(fp);\r | |
902 | return NULL;\r | |
903 | }\r | |
904 | buf = PyString_AsString(raw_data);\r | |
905 | \r | |
906 | err = fseek(fp, file_offset, 0);\r | |
907 | if (err == 0) {\r | |
908 | bytes_read = fread(buf, 1, data_size, fp);\r | |
909 | } else {\r | |
910 | fclose(fp);\r | |
911 | PyErr_Format(ZipImportError, "can't read Zip file: %s", archive);\r | |
912 | return NULL;\r | |
913 | }\r | |
914 | fclose(fp);\r | |
915 | if (err || bytes_read != data_size) {\r | |
916 | PyErr_SetString(PyExc_IOError,\r | |
917 | "zipimport: can't read data");\r | |
918 | Py_DECREF(raw_data);\r | |
919 | return NULL;\r | |
920 | }\r | |
921 | \r | |
922 | if (compress != 0) {\r | |
923 | buf[data_size] = 'Z'; /* saw this in zipfile.py */\r | |
924 | data_size++;\r | |
925 | }\r | |
926 | buf[data_size] = '\0';\r | |
927 | \r | |
928 | if (compress == 0) /* data is not compressed */\r | |
929 | return raw_data;\r | |
930 | \r | |
931 | /* Decompress with zlib */\r | |
932 | decompress = get_decompress_func();\r | |
933 | if (decompress == NULL) {\r | |
934 | PyErr_SetString(ZipImportError,\r | |
935 | "can't decompress data; "\r | |
936 | "zlib not available");\r | |
937 | goto error;\r | |
938 | }\r | |
939 | data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);\r | |
940 | Py_DECREF(decompress);\r | |
941 | error:\r | |
942 | Py_DECREF(raw_data);\r | |
943 | return data;\r | |
944 | }\r | |
945 | \r | |
946 | /* Lenient date/time comparison function. The precision of the mtime\r | |
947 | in the archive is lower than the mtime stored in a .pyc: we\r | |
948 | must allow a difference of at most one second. */\r | |
949 | static int\r | |
950 | eq_mtime(time_t t1, time_t t2)\r | |
951 | {\r | |
952 | time_t d = t1 - t2;\r | |
953 | if (d < 0)\r | |
954 | d = -d;\r | |
955 | /* dostime only stores even seconds, so be lenient */\r | |
956 | return d <= 1;\r | |
957 | }\r | |
958 | \r | |
959 | /* Given the contents of a .py[co] file in a buffer, unmarshal the data\r | |
960 | and return the code object. Return None if it the magic word doesn't\r | |
961 | match (we do this instead of raising an exception as we fall back\r | |
962 | to .py if available and we don't want to mask other errors).\r | |
963 | Returns a new reference. */\r | |
964 | static PyObject *\r | |
965 | unmarshal_code(char *pathname, PyObject *data, time_t mtime)\r | |
966 | {\r | |
967 | PyObject *code;\r | |
968 | char *buf = PyString_AsString(data);\r | |
969 | Py_ssize_t size = PyString_Size(data);\r | |
970 | \r | |
971 | if (size <= 9) {\r | |
972 | PyErr_SetString(ZipImportError,\r | |
973 | "bad pyc data");\r | |
974 | return NULL;\r | |
975 | }\r | |
976 | \r | |
977 | if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {\r | |
978 | if (Py_VerboseFlag)\r | |
979 | PySys_WriteStderr("# %s has bad magic\n",\r | |
980 | pathname);\r | |
981 | Py_INCREF(Py_None);\r | |
982 | return Py_None; /* signal caller to try alternative */\r | |
983 | }\r | |
984 | \r | |
985 | if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),\r | |
986 | mtime)) {\r | |
987 | if (Py_VerboseFlag)\r | |
988 | PySys_WriteStderr("# %s has bad mtime\n",\r | |
989 | pathname);\r | |
990 | Py_INCREF(Py_None);\r | |
991 | return Py_None; /* signal caller to try alternative */\r | |
992 | }\r | |
993 | \r | |
994 | code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);\r | |
995 | if (code == NULL)\r | |
996 | return NULL;\r | |
997 | if (!PyCode_Check(code)) {\r | |
998 | Py_DECREF(code);\r | |
999 | PyErr_Format(PyExc_TypeError,\r | |
1000 | "compiled module %.200s is not a code object",\r | |
1001 | pathname);\r | |
1002 | return NULL;\r | |
1003 | }\r | |
1004 | return code;\r | |
1005 | }\r | |
1006 | \r | |
1007 | /* Replace any occurances of "\r\n?" in the input string with "\n".\r | |
1008 | This converts DOS and Mac line endings to Unix line endings.\r | |
1009 | Also append a trailing "\n" to be compatible with\r | |
1010 | PyParser_SimpleParseFile(). Returns a new reference. */\r | |
1011 | static PyObject *\r | |
1012 | normalize_line_endings(PyObject *source)\r | |
1013 | {\r | |
1014 | char *buf, *q, *p = PyString_AsString(source);\r | |
1015 | PyObject *fixed_source;\r | |
1016 | \r | |
1017 | if (!p)\r | |
1018 | return NULL;\r | |
1019 | \r | |
1020 | /* one char extra for trailing \n and one for terminating \0 */\r | |
1021 | buf = (char *)PyMem_Malloc(PyString_Size(source) + 2);\r | |
1022 | if (buf == NULL) {\r | |
1023 | PyErr_SetString(PyExc_MemoryError,\r | |
1024 | "zipimport: no memory to allocate "\r | |
1025 | "source buffer");\r | |
1026 | return NULL;\r | |
1027 | }\r | |
1028 | /* replace "\r\n?" by "\n" */\r | |
1029 | for (q = buf; *p != '\0'; p++) {\r | |
1030 | if (*p == '\r') {\r | |
1031 | *q++ = '\n';\r | |
1032 | if (*(p + 1) == '\n')\r | |
1033 | p++;\r | |
1034 | }\r | |
1035 | else\r | |
1036 | *q++ = *p;\r | |
1037 | }\r | |
1038 | *q++ = '\n'; /* add trailing \n */\r | |
1039 | *q = '\0';\r | |
1040 | fixed_source = PyString_FromString(buf);\r | |
1041 | PyMem_Free(buf);\r | |
1042 | return fixed_source;\r | |
1043 | }\r | |
1044 | \r | |
1045 | /* Given a string buffer containing Python source code, compile it\r | |
1046 | return and return a code object as a new reference. */\r | |
1047 | static PyObject *\r | |
1048 | compile_source(char *pathname, PyObject *source)\r | |
1049 | {\r | |
1050 | PyObject *code, *fixed_source;\r | |
1051 | \r | |
1052 | fixed_source = normalize_line_endings(source);\r | |
1053 | if (fixed_source == NULL)\r | |
1054 | return NULL;\r | |
1055 | \r | |
1056 | code = Py_CompileString(PyString_AsString(fixed_source), pathname,\r | |
1057 | Py_file_input);\r | |
1058 | Py_DECREF(fixed_source);\r | |
1059 | return code;\r | |
1060 | }\r | |
1061 | \r | |
1062 | /* Convert the date/time values found in the Zip archive to a value\r | |
1063 | that's compatible with the time stamp stored in .pyc files. */\r | |
1064 | static time_t\r | |
1065 | parse_dostime(int dostime, int dosdate)\r | |
1066 | {\r | |
1067 | struct tm stm;\r | |
1068 | \r | |
1069 | memset((void *) &stm, '\0', sizeof(stm));\r | |
1070 | \r | |
1071 | stm.tm_sec = (dostime & 0x1f) * 2;\r | |
1072 | stm.tm_min = (dostime >> 5) & 0x3f;\r | |
1073 | stm.tm_hour = (dostime >> 11) & 0x1f;\r | |
1074 | stm.tm_mday = dosdate & 0x1f;\r | |
1075 | stm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;\r | |
1076 | stm.tm_year = ((dosdate >> 9) & 0x7f) + 80;\r | |
1077 | stm.tm_isdst = -1; /* wday/yday is ignored */\r | |
1078 | \r | |
1079 | return mktime(&stm);\r | |
1080 | }\r | |
1081 | \r | |
1082 | /* Given a path to a .pyc or .pyo file in the archive, return the\r | |
1083 | modification time of the matching .py file, or 0 if no source\r | |
1084 | is available. */\r | |
1085 | static time_t\r | |
1086 | get_mtime_of_source(ZipImporter *self, char *path)\r | |
1087 | {\r | |
1088 | PyObject *toc_entry;\r | |
1089 | time_t mtime = 0;\r | |
1090 | Py_ssize_t lastchar = strlen(path) - 1;\r | |
1091 | char savechar = path[lastchar];\r | |
1092 | path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */\r | |
1093 | toc_entry = PyDict_GetItemString(self->files, path);\r | |
1094 | if (toc_entry != NULL && PyTuple_Check(toc_entry) &&\r | |
1095 | PyTuple_Size(toc_entry) == 8) {\r | |
1096 | /* fetch the time stamp of the .py file for comparison\r | |
1097 | with an embedded pyc time stamp */\r | |
1098 | int time, date;\r | |
1099 | time = PyInt_AsLong(PyTuple_GetItem(toc_entry, 5));\r | |
1100 | date = PyInt_AsLong(PyTuple_GetItem(toc_entry, 6));\r | |
1101 | mtime = parse_dostime(time, date);\r | |
1102 | }\r | |
1103 | path[lastchar] = savechar;\r | |
1104 | return mtime;\r | |
1105 | }\r | |
1106 | \r | |
1107 | /* Return the code object for the module named by 'fullname' from the\r | |
1108 | Zip archive as a new reference. */\r | |
1109 | static PyObject *\r | |
1110 | get_code_from_data(ZipImporter *self, int ispackage, int isbytecode,\r | |
1111 | time_t mtime, PyObject *toc_entry)\r | |
1112 | {\r | |
1113 | PyObject *data, *code;\r | |
1114 | char *modpath;\r | |
1115 | char *archive = PyString_AsString(self->archive);\r | |
1116 | \r | |
1117 | if (archive == NULL)\r | |
1118 | return NULL;\r | |
1119 | \r | |
1120 | data = get_data(archive, toc_entry);\r | |
1121 | if (data == NULL)\r | |
1122 | return NULL;\r | |
1123 | \r | |
1124 | modpath = PyString_AsString(PyTuple_GetItem(toc_entry, 0));\r | |
1125 | \r | |
1126 | if (isbytecode) {\r | |
1127 | code = unmarshal_code(modpath, data, mtime);\r | |
1128 | }\r | |
1129 | else {\r | |
1130 | code = compile_source(modpath, data);\r | |
1131 | }\r | |
1132 | Py_DECREF(data);\r | |
1133 | return code;\r | |
1134 | }\r | |
1135 | \r | |
1136 | /* Get the code object associated with the module specified by\r | |
1137 | 'fullname'. */\r | |
1138 | static PyObject *\r | |
1139 | get_module_code(ZipImporter *self, char *fullname,\r | |
1140 | int *p_ispackage, char **p_modpath)\r | |
1141 | {\r | |
1142 | PyObject *toc_entry;\r | |
1143 | char *subname, path[MAXPATHLEN + 1];\r | |
1144 | int len;\r | |
1145 | struct st_zip_searchorder *zso;\r | |
1146 | \r | |
1147 | subname = get_subname(fullname);\r | |
1148 | \r | |
1149 | len = make_filename(PyString_AsString(self->prefix), subname, path);\r | |
1150 | if (len < 0)\r | |
1151 | return NULL;\r | |
1152 | \r | |
1153 | for (zso = zip_searchorder; *zso->suffix; zso++) {\r | |
1154 | PyObject *code = NULL;\r | |
1155 | \r | |
1156 | strcpy(path + len, zso->suffix);\r | |
1157 | if (Py_VerboseFlag > 1)\r | |
1158 | PySys_WriteStderr("# trying %s%c%s\n",\r | |
1159 | PyString_AsString(self->archive),\r | |
1160 | SEP, path);\r | |
1161 | toc_entry = PyDict_GetItemString(self->files, path);\r | |
1162 | if (toc_entry != NULL) {\r | |
1163 | time_t mtime = 0;\r | |
1164 | int ispackage = zso->type & IS_PACKAGE;\r | |
1165 | int isbytecode = zso->type & IS_BYTECODE;\r | |
1166 | \r | |
1167 | if (isbytecode)\r | |
1168 | mtime = get_mtime_of_source(self, path);\r | |
1169 | if (p_ispackage != NULL)\r | |
1170 | *p_ispackage = ispackage;\r | |
1171 | code = get_code_from_data(self, ispackage,\r | |
1172 | isbytecode, mtime,\r | |
1173 | toc_entry);\r | |
1174 | if (code == Py_None) {\r | |
1175 | /* bad magic number or non-matching mtime\r | |
1176 | in byte code, try next */\r | |
1177 | Py_DECREF(code);\r | |
1178 | continue;\r | |
1179 | }\r | |
1180 | if (code != NULL && p_modpath != NULL)\r | |
1181 | *p_modpath = PyString_AsString(\r | |
1182 | PyTuple_GetItem(toc_entry, 0));\r | |
1183 | return code;\r | |
1184 | }\r | |
1185 | }\r | |
1186 | PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname);\r | |
1187 | return NULL;\r | |
1188 | }\r | |
1189 | \r | |
1190 | \r | |
1191 | /* Module init */\r | |
1192 | \r | |
1193 | PyDoc_STRVAR(zipimport_doc,\r | |
1194 | "zipimport provides support for importing Python modules from Zip archives.\n\\r | |
1195 | \n\\r | |
1196 | This module exports three objects:\n\\r | |
1197 | - zipimporter: a class; its constructor takes a path to a Zip archive.\n\\r | |
1198 | - ZipImportError: exception raised by zipimporter objects. It's a\n\\r | |
1199 | subclass of ImportError, so it can be caught as ImportError, too.\n\\r | |
1200 | - _zip_directory_cache: a dict, mapping archive paths to zip directory\n\\r | |
1201 | info dicts, as used in zipimporter._files.\n\\r | |
1202 | \n\\r | |
1203 | It is usually not needed to use the zipimport module explicitly; it is\n\\r | |
1204 | used by the builtin import mechanism for sys.path items that are paths\n\\r | |
1205 | to Zip archives.");\r | |
1206 | \r | |
1207 | PyMODINIT_FUNC\r | |
1208 | initzipimport(void)\r | |
1209 | {\r | |
1210 | PyObject *mod;\r | |
1211 | \r | |
1212 | if (PyType_Ready(&ZipImporter_Type) < 0)\r | |
1213 | return;\r | |
1214 | \r | |
1215 | /* Correct directory separator */\r | |
1216 | zip_searchorder[0].suffix[0] = SEP;\r | |
1217 | zip_searchorder[1].suffix[0] = SEP;\r | |
1218 | zip_searchorder[2].suffix[0] = SEP;\r | |
1219 | if (Py_OptimizeFlag) {\r | |
1220 | /* Reverse *.pyc and *.pyo */\r | |
1221 | struct st_zip_searchorder tmp;\r | |
1222 | tmp = zip_searchorder[0];\r | |
1223 | zip_searchorder[0] = zip_searchorder[1];\r | |
1224 | zip_searchorder[1] = tmp;\r | |
1225 | tmp = zip_searchorder[3];\r | |
1226 | zip_searchorder[3] = zip_searchorder[4];\r | |
1227 | zip_searchorder[4] = tmp;\r | |
1228 | }\r | |
1229 | \r | |
1230 | mod = Py_InitModule4("zipimport", NULL, zipimport_doc,\r | |
1231 | NULL, PYTHON_API_VERSION);\r | |
1232 | if (mod == NULL)\r | |
1233 | return;\r | |
1234 | \r | |
1235 | ZipImportError = PyErr_NewException("zipimport.ZipImportError",\r | |
1236 | PyExc_ImportError, NULL);\r | |
1237 | if (ZipImportError == NULL)\r | |
1238 | return;\r | |
1239 | \r | |
1240 | Py_INCREF(ZipImportError);\r | |
1241 | if (PyModule_AddObject(mod, "ZipImportError",\r | |
1242 | ZipImportError) < 0)\r | |
1243 | return;\r | |
1244 | \r | |
1245 | Py_INCREF(&ZipImporter_Type);\r | |
1246 | if (PyModule_AddObject(mod, "zipimporter",\r | |
1247 | (PyObject *)&ZipImporter_Type) < 0)\r | |
1248 | return;\r | |
1249 | \r | |
1250 | zip_directory_cache = PyDict_New();\r | |
1251 | if (zip_directory_cache == NULL)\r | |
1252 | return;\r | |
1253 | Py_INCREF(zip_directory_cache);\r | |
1254 | if (PyModule_AddObject(mod, "_zip_directory_cache",\r | |
1255 | zip_directory_cache) < 0)\r | |
1256 | return;\r | |
1257 | }\r |