[Distutils] Make easy_install script updates atomic / allow in multi-user env

ryles rylesny at gmail.com
Tue Aug 18 03:43:56 CEST 2009


In setuptools/command/easy_install.py, easy_install.write_script is
the method called to install each of a package's scripts. It contains
the following:

f = open(target,"w"+mode)
f.write(contents)
f.close()
chmod(target,0755)

opening the file with "w" will cause it to truncate, and then there is
a race between the open and the write. Further, due to buffering there
is even no guarantee that a user will see either an empty or complete
version of the script during this time. It should be safer to instead
write to a temporary file and then use shutil.move, which, on Unix-
like systems at least, will call rename() (i.e. what /bin/mv would
do). renaming is atomic and allows the old version to remain in tact
(anonymously) if any process had it open for reading, and also ensures
that no process will see an incomplete version.


The above code can also create problems in a multi-user environment.

chmod() is inflexibly giving only the owner write access. The author
may have purposely given the script (the original non-wrapper version,
at least) group write access so that other developers could install
newer versions of the package at a later time. The chmod() call blocks
this attempt.

More importantly, directory permissions are ignored. That is, even if
the script itself is not writable (necessarily true with the current
code), its parent directory may purposely be writable so that newer
versions can be added. Using shutl.move will address this since it
operates on the directory and not the file itself. This is arguable
the correct semantics anyway: "install a new version of the script",
not "edit the existing script".


More information about the Distutils-SIG mailing list