Commit 8b177917 authored by Julien Muchembled's avatar Julien Muchembled

jinja2: safer code for FS accesses

Although very unlikely here, it's good pratice to write code without possible
race conditions. The only remaining one here is when anouther process create
a file (with the same output path) between its deletion and its creation.
parent 594d4bfc
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# #
############################################################################## ##############################################################################
import errno
import os import os
import json import json
import zc.buildout import zc.buildout
...@@ -37,6 +38,9 @@ DEFAULT_IMPORT_DELIMITER = '/' ...@@ -37,6 +38,9 @@ DEFAULT_IMPORT_DELIMITER = '/'
@contextmanager @contextmanager
def umask(mask): def umask(mask):
if mask is None:
yield
return
original = os.umask(mask) original = os.umask(mask)
try: try:
yield original yield original
...@@ -124,8 +128,9 @@ LOADER_TYPE_DICT = { ...@@ -124,8 +128,9 @@ LOADER_TYPE_DICT = {
} }
class Recipe(object): class Recipe(object):
mode = None mode = 0777 # BBB: 0666 may have been a better default value
loader = None loader = None
umask = None
def __init__(self, buildout, name, options): def __init__(self, buildout, name, options):
self.template = zc.buildout.download.Download( self.template = zc.buildout.download.Download(
...@@ -175,26 +180,23 @@ class Recipe(object): ...@@ -175,26 +180,23 @@ class Recipe(object):
umask_value = options.get('umask') umask_value = options.get('umask')
if umask_value: if umask_value:
self.umask = int(umask_value, 8) self.umask = int(umask_value, 8)
else:
self.umask = os.umask(0)
os.umask(self.umask)
def install(self): def install(self):
if os.path.lexists(self.rendered):
# Unlink any existing file, so umask is always applied. # Unlink any existing file, so umask is always applied.
try:
os.unlink(self.rendered) os.unlink(self.rendered)
except OSError, e:
if e.errno != errno.ENOENT:
raise
with umask(self.umask): with umask(self.umask):
outdir = os.path.dirname(self.rendered) outdir = os.path.dirname(self.rendered)
if outdir and not os.path.exists(outdir): if outdir and not os.path.exists(outdir):
os.makedirs(outdir) os.makedirs(outdir)
# XXX: open doesn't allow providing a filesystem mode, so use # XXX: open doesn't allow providing a filesystem mode, so use
# os.open and os.fdopen instead. # os.open and os.fdopen instead.
out_fd = os.open(self.rendered, with os.fdopen(os.open(self.rendered,
os.O_CREAT | os.O_TRUNC | os.O_WRONLY, os.O_CREAT | os.O_EXCL | os.O_WRONLY,
) self.mode), 'w') as out:
if self.mode is not None:
os.fchmod(out_fd, self.mode)
with os.fdopen(out_fd, 'w') as out:
out.write( out.write(
Environment( Environment(
extensions=self.extension_list, extensions=self.extension_list,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment