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