summaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2012-12-31 21:40:42 -0600
committerBenjamin Peterson <benjamin@python.org>2012-12-31 21:40:42 -0600
commit0bb371a5277c3fe5c95a0f364eb9567b16476ff3 (patch)
tree410dd0662880ac920b2a92d9a02f3a1b4d180301 /Python
parentb090ba1ed23b10b2f954a41a48b32d6ecb98f1af (diff)
parent4825a64df6e59ea47f33b872e726b38b04e7bb48 (diff)
downloadcpython-0bb371a5277c3fe5c95a0f364eb9567b16476ff3.tar.gz
merge heads
Diffstat (limited to 'Python')
-rw-r--r--Python/import.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/Python/import.c b/Python/import.c
index 7daba06ad2..92363b3937 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -904,10 +904,9 @@ open_exclusive(char *filename, mode_t mode)
remove the file. */
static void
-write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
+write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat, time_t mtime)
{
FILE *fp;
- time_t mtime = srcstat->st_mtime;
#ifdef MS_WINDOWS /* since Windows uses different permissions */
mode_t mode = srcstat->st_mode & ~S_IEXEC;
/* Issue #6074: We ensure user write access, so we can delete it later
@@ -993,6 +992,38 @@ update_compiled_module(PyCodeObject *co, char *pathname)
return 1;
}
+#ifdef MS_WINDOWS
+
+/* Seconds between 1.1.1601 and 1.1.1970 */
+static __int64 secs_between_epochs = 11644473600;
+
+/* Get mtime from file pointer. */
+
+static time_t
+win32_mtime(FILE *fp, char *pathname)
+{
+ __int64 filetime;
+ HANDLE fh;
+ BY_HANDLE_FILE_INFORMATION file_information;
+
+ fh = (HANDLE)_get_osfhandle(fileno(fp));
+ if (fh == INVALID_HANDLE_VALUE ||
+ !GetFileInformationByHandle(fh, &file_information)) {
+ PyErr_Format(PyExc_RuntimeError,
+ "unable to get file status from '%s'",
+ pathname);
+ return -1;
+ }
+ /* filetime represents the number of 100ns intervals since
+ 1.1.1601 (UTC). Convert to seconds since 1.1.1970 (UTC). */
+ filetime = (__int64)file_information.ftLastWriteTime.dwHighDateTime << 32 |
+ file_information.ftLastWriteTime.dwLowDateTime;
+ return filetime / 10000000 - secs_between_epochs;
+}
+
+#endif /* #ifdef MS_WINDOWS */
+
+
/* Load a source module from a given file and return its module
object WITH INCREMENTED REFERENCE COUNT. If there's a matching
byte-compiled file, use that instead. */
@@ -1006,6 +1037,7 @@ load_source_module(char *name, char *pathname, FILE *fp)
char *cpathname;
PyCodeObject *co = NULL;
PyObject *m;
+ time_t mtime;
if (fstat(fileno(fp), &st) != 0) {
PyErr_Format(PyExc_RuntimeError,
@@ -1013,13 +1045,21 @@ load_source_module(char *name, char *pathname, FILE *fp)
pathname);
return NULL;
}
- if (sizeof st.st_mtime > 4) {
+
+#ifdef MS_WINDOWS
+ mtime = win32_mtime(fp, pathname);
+ if (mtime == (time_t)-1 && PyErr_Occurred())
+ return NULL;
+#else
+ mtime = st.st_mtime;
+#endif
+ if (sizeof mtime > 4) {
/* Python's .pyc timestamp handling presumes that the timestamp fits
in 4 bytes. Since the code only does an equality comparison,
ordering is not important and we can safely ignore the higher bits
(collisions are extremely unlikely).
*/
- st.st_mtime &= 0xFFFFFFFF;
+ mtime &= 0xFFFFFFFF;
}
buf = PyMem_MALLOC(MAXPATHLEN+1);
if (buf == NULL) {
@@ -1028,7 +1068,7 @@ load_source_module(char *name, char *pathname, FILE *fp)
cpathname = make_compiled_pathname(pathname, buf,
(size_t)MAXPATHLEN + 1);
if (cpathname != NULL &&
- (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) {
+ (fpc = check_compiled_module(pathname, mtime, cpathname))) {
co = read_compiled_module(cpathname, fpc);
fclose(fpc);
if (co == NULL)
@@ -1053,7 +1093,7 @@ load_source_module(char *name, char *pathname, FILE *fp)
if (b < 0)
goto error_exit;
if (!b)
- write_compiled_module(co, cpathname, &st);
+ write_compiled_module(co, cpathname, &st, mtime);
}
}
m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname);