Commit 4138d39f authored by Iustin Pop's avatar Iustin Pop
Browse files

Add a "safe" file wrapper over WriteFile


Signed-off-by: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent 9e100285
......@@ -1912,6 +1912,31 @@ def VerifyFileID(fi_disk, fi_ours):
return (d1, i1) == (d2, i2) and m1 <= m2
def SafeWriteFile(file_name, file_id, **kwargs):
"""Wraper over L{WriteFile} that locks the target file.
By keeping the target file locked during WriteFile, we ensure that
cooperating writers will safely serialise access to the file.
@type file_name: str
@param file_name: the target filename
@type file_id: tuple
@param file_id: a result from L{GetFileID}
"""
fd = os.open(file_name, os.O_RDONLY | os.O_CREAT)
try:
LockFile(fd)
if file_id is not None:
disk_id = GetFileID(fd=fd)
if not VerifyFileID(disk_id, file_id):
raise errors.LockError("Cannot overwrite file %s, it has been modified"
" since last written" % file_name)
return WriteFile(file_name, **kwargs)
finally:
os.close(fd)
def ReadOneLineFile(file_name, strict=False):
"""Return the first non-empty line from a file.
......
......@@ -2374,6 +2374,21 @@ class TestFileID(testutils.GanetiTestCase):
finally:
os.close(fd)
def testWriteFile(self):
name = self._CreateTempFile()
oldi = utils.GetFileID(path=name)
mtime = oldi[2]
os.utime(name, (mtime + 10, mtime + 10))
self.assertRaises(errors.LockError, utils.SafeWriteFile, name,
oldi, data="")
os.utime(name, (mtime - 10, mtime - 10))
utils.SafeWriteFile(name, oldi, data="")
oldi = utils.GetFileID(path=name)
mtime = oldi[2]
os.utime(name, (mtime + 10, mtime + 10))
# this doesn't raise, since we passed None
utils.SafeWriteFile(name, None, data="")
if __name__ == '__main__':
testutils.GanetiTestProgram()
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