Message256849
You also forgot about two things:
1. set temporary file permissions before rename
2. fsync(open(os.dirname(temporaryfile)))
3. if original file name is symlink, replace will works wrong. os.realpath should be used.
So, here are real life function, that we use in production:
# TODO: save_mtime, save_selinux, extended attr, chattrs and so on...
# TODO: malicious user may replace directory with another while writing to file,
# so we should use open directory first, and then use openat() and renameat()
# with relative filename instead of specifying absolute path.
# also NameTemporaryFile should allow to specify dir=<dir_file_descriptor>
@contextmanager
def replace_file(path, save_perms=False, fsync=True, **kwargs):
realpath = os.path.realpath(path)
operating_dir = os.path.dirname(realpath)
uid = None
gid = None
mode = None
if save_perms:
try:
stinfo = os.lstat(realpath)
uid = stinfo.st_uid
gid = stinfo.st_gid
mode = stinfo.st_mode
except OSError as e:
if e.errno != errno.ENOENT:
raise
with NamedTemporaryFile(dir=operating_dir, **kwargs) as fff:
filedes = fff.fileno()
if None not in (uid, gid, mode):
os.fchown(filedes, uid, gid)
os.fchmod(filedes, mode & 0o7777)
yield fff
# survive application crash
fff.flush()
if fsync:
# survive power outage, is not required if that is temporary file
os.fsync(filedes)
os.rename(fff.name, realpath)
# see http://bugs.python.org/issue21579
fff._closer.delete = False
if fsync:
# Sync directory: http://stackoverflow.com/questions/3764822/how-to-durably-rename-a-file-in-posix
dirfd = os.open(operating_dir, os.O_RDONLY | os.O_CLOEXEC | os.O_DIRECTORY)
try:
os.fsync(dirfd)
finally:
os.close(dirfd) |
|
Date |
User |
Action |
Args |
2015-12-22 18:41:09 | socketpair | set | recipients:
+ socketpair, loewis, barry, exarkun, ncoghlan, pitrou, vstinner, eric.smith, giampaolo.rodola, tarek, eric.araujo, Arfrever, olemis, meatballhat, milko.krachounov, neologix, martin.panter |
2015-12-22 18:41:09 | socketpair | set | messageid: <1450809669.27.0.106825521484.issue8604@psf.upfronthosting.co.za> |
2015-12-22 18:41:09 | socketpair | link | issue8604 messages |
2015-12-22 18:41:08 | socketpair | create | |
|