return;
}
PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION);
- /* First write a 0 for mtime */
+ /* First write a 0 for mtime and size */
+ PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
- /* Now write the true mtime and size */
+ fflush(fp);
- assert(mtime < LONG_MAX);
++ /* Now write the true mtime and size (as 32-bit fields) */
+ fseek(fp, 4L, 0);
++ assert(mtime <= 0xFFFFFFFF);
+ PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION);
+ PyMarshal_WriteLongToFile(size, fp, Py_MARSHAL_VERSION);
if (fflush(fp) != 0 || ferror(fp)) {
if (Py_VerboseFlag)
- PySys_WriteStderr("# can't write %s\n", cpathname);
+ PySys_FormatStderr("# can't write %R\n", cpathname);
/* Don't keep partial file */
fclose(fp);
- (void) unlink(cpathname);
+#ifdef MS_WINDOWS
+ (void)DeleteFileW(wpathname_tmp);
+ Py_DECREF(cpathname_tmp);
+#else
+ (void) unlink(PyBytes_AS_STRING(cpathbytes_tmp));
+ Py_DECREF(cpathbytes);
+ Py_DECREF(cpathbytes_tmp);
+#endif
return;
}
- /* Now write the true mtime (as a 32-bit field) */
- fseek(fp, 4L, 0);
- assert(mtime <= 0xFFFFFFFF);
- PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION);
- fflush(fp);
fclose(fp);
+ /* Do a (hopefully) atomic rename */
+#ifdef MS_WINDOWS
+ if (!MoveFileExW(wpathname_tmp, wpathname, MOVEFILE_REPLACE_EXISTING)) {
+ if (Py_VerboseFlag)
+ PySys_FormatStderr("# can't write %R\n", cpathname);
+ /* Don't keep tmp file */
+ (void) DeleteFileW(wpathname_tmp);
+ Py_DECREF(cpathname_tmp);
+ return;
+ }
+ Py_DECREF(cpathname_tmp);
+#else
+ if (rename(PyBytes_AS_STRING(cpathbytes_tmp),
+ PyBytes_AS_STRING(cpathbytes))) {
+ if (Py_VerboseFlag)
+ PySys_FormatStderr("# can't write %R\n", cpathname);
+ /* Don't keep tmp file */
+ unlink(PyBytes_AS_STRING(cpathbytes_tmp));
+ Py_DECREF(cpathbytes);
+ Py_DECREF(cpathbytes_tmp);
+ return;
+ }
+ Py_DECREF(cpathbytes);
+ Py_DECREF(cpathbytes_tmp);
+#endif
if (Py_VerboseFlag)
- PySys_WriteStderr("# wrote %s\n", cpathname);
+ PySys_FormatStderr("# wrote %R\n", cpathname);
}
static void
if (fstat(fileno(fp), &st) != 0) {
PyErr_Format(PyExc_RuntimeError,
- "unable to get file status from '%s'",
+ "unable to get file status from %R",
pathname);
- return NULL;
+ goto error;
}
- #if SIZEOF_TIME_T > 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;
- #endif
+ if (sizeof st.st_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;
+ }
- cpathname = make_compiled_pathname(
- pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag);
- if (cpathname != NULL &&
- (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) {
+ if (PyUnicode_READY(pathname) < 0)
+ return NULL;
+ cpathname = make_compiled_pathname(pathname, !Py_OptimizeFlag);
+
+ if (cpathname != NULL)
+ fpc = check_compiled_module(pathname, &st, cpathname);
+ else
+ fpc = NULL;
+
+ if (fpc) {
co = read_compiled_module(cpathname, fpc);
fclose(fpc);
if (co == NULL)