1 diff -ru Python-2.6.7-orig/Python/import.c Python-2.6.7/Python/import.c
2 --- Python-2.6.7-orig/Python/import.c 2010-05-20 18:41:08.000000000 +0000
3 +++ Python-2.6.7/Python/import.c 2012-02-15 20:05:08.692629958 +0000
4 @@ -868,8 +868,9 @@
5
6 /* Write a compiled module to a file, placing the time of last
7 modification of its source into the header.
8 - Errors are ignored, if a write error occurs an attempt is made to
9 - remove the file. */
10 + Write to a temporary file first so that creating the file is atomic.
11 + Errors are ignored, if a write/unlink/rename error occurs an attempt
12 + is made to remove the temporary file. */
13
14 static void
15 write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
16 @@ -881,12 +882,21 @@
17 #else
18 mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH;
19 #endif
20 + char *tmppathname;
21 +
22 + /* the temporary file is called cpathname + ".tmp" */
23 + if ((tmppathname = PyMem_Malloc(strlen(cpathname) + strlen(".tmp") + 1))
24 + == NULL) {
25 + return;
26 + }
27 + sprintf (tmppathname, "%s.tmp", cpathname);
28 + fp = open_exclusive(tmppathname, mode);
29
30 - fp = open_exclusive(cpathname, mode);
31 if (fp == NULL) {
32 if (Py_VerboseFlag)
33 PySys_WriteStderr(
34 - "# can't create %s\n", cpathname);
35 + "# can't create %s\n", tmppathname);
36 + PyMem_Free(tmppathname);
37 return;
38 }
39 PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION);
40 @@ -895,10 +905,11 @@
41 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
42 if (fflush(fp) != 0 || ferror(fp)) {
43 if (Py_VerboseFlag)
44 - PySys_WriteStderr("# can't write %s\n", cpathname);
45 + PySys_WriteStderr("# can't write %s\n", tmppathname);
46 /* Don't keep partial file */
47 fclose(fp);
48 - (void) unlink(cpathname);
49 + (void) unlink(tmppathname);
50 + PyMem_Free(tmppathname);
51 return;
52 }
53 /* Now write the true mtime */
54 @@ -907,8 +918,30 @@
55 PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION);
56 fflush(fp);
57 fclose(fp);
58 + /* Delete the old compiled file, if exists */
59 + if (unlink (cpathname)) {
60 + if ((errno != ENOENT)) {
61 + /* the file exists but could not be deleted */
62 + if (Py_VerboseFlag)
63 + PySys_WriteStderr(
64 + "# can't unlink %s\n", cpathname);
65 + (void) unlink(tmppathname);
66 + PyMem_Free(tmppathname);
67 + return;
68 + }
69 + }
70 + /* rename the tmp file to the real file name */
71 + if (rename (tmppathname, cpathname)) {
72 + if (Py_VerboseFlag)
73 + PySys_WriteStderr(
74 + "# can't rename %s to %s\n", tmppathname, cpathname);
75 + (void) unlink(tmppathname);
76 + PyMem_Free(tmppathname);
77 + return;
78 + }
79 if (Py_VerboseFlag)
80 PySys_WriteStderr("# wrote %s\n", cpathname);
81 + PyMem_Free(tmppathname);
82 }
83
84 static void