fix: atomic save keeps the store's file permissions
T1-9: _save wrote a fresh temp file with umask permissions and os.replace'd it over the target, so a chmod 600 store became 0644 after the first set(). copy the target's mode onto the temp file before the payload is written. Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
1 parent
4ba768a3bf
commit
8607046fe9
1 file changed
+6
-1
+6
-1
@@ -18,6 +18,7 @@ cross-process storage.
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import json
|
||||
import time
|
||||
import asyncio
|
||||
@@ -117,7 +118,9 @@ class AioKV:
|
||||
"""write atomically: temp file in the same dir, then os.replace over the realpath'd
|
||||
target (symlink-safe). process-crash safe (a crash mid-write leaves the prior good
|
||||
file intact), NOT power-loss safe - no fsync, so an OS/power failure can still lose
|
||||
the last write (acceptable: reconstructible single-process state, not a db)"""
|
||||
the last write (acceptable: reconstructible single-process state, not a db). an
|
||||
existing target's permission bits are copied onto the temp file before the payload
|
||||
is written, so a chmod 600 store stays 600 instead of taking the umask default"""
|
||||
target = await asyncio.to_thread(os.path.realpath, self.file)
|
||||
directory = os.path.dirname(target) or "."
|
||||
await asyncio.to_thread(os.makedirs, directory, exist_ok=True)
|
||||
@@ -127,6 +130,8 @@ class AioKV:
|
||||
tmp = f"{target}.{os.getpid()}.tmp"
|
||||
try:
|
||||
async with aiofiles.open(tmp, mode="w", encoding="utf-8") as f:
|
||||
if await asyncio.to_thread(os.path.exists, target):
|
||||
await asyncio.to_thread(shutil.copymode, target, tmp)
|
||||
await f.write(payload)
|
||||
await asyncio.to_thread(os.replace, tmp, target)
|
||||
except Exception:
|
||||
|
||||
Reference in new issue
Block a user