add option for file creation mode
This commit is contained in:
@@ -192,6 +192,7 @@ class StoreConfig(BaseConfig):
|
|||||||
"properties": {
|
"properties": {
|
||||||
"type": {"type": "string"},
|
"type": {"type": "string"},
|
||||||
"directory": {"type": "string"},
|
"directory": {"type": "string"},
|
||||||
|
"mode": {"type": "string"},
|
||||||
"metavar": {"type": "string"},
|
"metavar": {"type": "string"},
|
||||||
"original": {"type": "boolean", "default": True}}}}
|
"original": {"type": "boolean", "default": True}}}}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class FileMailStorage(BaseMailStorage):
|
|||||||
_headersonly = False
|
_headersonly = False
|
||||||
|
|
||||||
def __init__(self, directory, original=False, metadata=False, metavar=None,
|
def __init__(self, directory, original=False, metadata=False, metavar=None,
|
||||||
pretend=False):
|
mode=None, pretend=False):
|
||||||
super().__init__(original, metadata, metavar, pretend)
|
super().__init__(original, metadata, metavar, pretend)
|
||||||
# check if directory exists and is writable
|
# check if directory exists and is writable
|
||||||
if not os.path.isdir(directory) or \
|
if not os.path.isdir(directory) or \
|
||||||
@@ -82,6 +82,13 @@ class FileMailStorage(BaseMailStorage):
|
|||||||
f"directory '{directory}' does not exist or is "
|
f"directory '{directory}' does not exist or is "
|
||||||
f"not writable")
|
f"not writable")
|
||||||
self.directory = directory
|
self.directory = directory
|
||||||
|
try:
|
||||||
|
self.mode = int(mode, 8) if mode is not None else None
|
||||||
|
if self.mode is not None and self.mode > 511:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
raise RuntimeError(f"invalid mode '{mode}'")
|
||||||
|
|
||||||
self._metadata_suffix = ".metadata"
|
self._metadata_suffix = ".metadata"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@@ -104,15 +111,33 @@ class FileMailStorage(BaseMailStorage):
|
|||||||
|
|
||||||
def _save_datafile(self, datafile, data):
|
def _save_datafile(self, datafile, data):
|
||||||
try:
|
try:
|
||||||
|
if self.mode is None:
|
||||||
with open(datafile, "wb") as f:
|
with open(datafile, "wb") as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
else:
|
||||||
|
umask = os.umask(0)
|
||||||
|
with open(
|
||||||
|
os.open(datafile, os.O_CREAT | os.O_WRONLY, self.mode),
|
||||||
|
"wb") as f:
|
||||||
|
f.write(data)
|
||||||
|
os.umask(umask)
|
||||||
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise RuntimeError(f"unable save data file: {e}")
|
raise RuntimeError(f"unable save data file: {e}")
|
||||||
|
|
||||||
def _save_metafile(self, metafile, metadata):
|
def _save_metafile(self, metafile, metadata):
|
||||||
try:
|
try:
|
||||||
|
if self.mode is None:
|
||||||
with open(metafile, "w") as f:
|
with open(metafile, "w") as f:
|
||||||
json.dump(metadata, f, indent=2)
|
json.dump(metadata, f, indent=2)
|
||||||
|
else:
|
||||||
|
umask = os.umask(0)
|
||||||
|
with open(
|
||||||
|
os.open(metafile, os.O_CREAT | os.O_WRONLY, self.mode),
|
||||||
|
"w") as f:
|
||||||
|
json.dump(metadata, f, indent=2)
|
||||||
|
os.umask(umask)
|
||||||
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise RuntimeError(f"unable to save metadata file: {e}")
|
raise RuntimeError(f"unable to save metadata file: {e}")
|
||||||
|
|
||||||
@@ -330,6 +355,7 @@ class Quarantine:
|
|||||||
"pretend": cfg["pretend"],
|
"pretend": cfg["pretend"],
|
||||||
"type": "store",
|
"type": "store",
|
||||||
"args": cfg["args"]["store"].get_config()})
|
"args": cfg["args"]["store"].get_config()})
|
||||||
|
store_cfg["args"]["metadata"] = True
|
||||||
self.store = Store(store_cfg, local_addrs, debug)
|
self.store = Store(store_cfg, local_addrs, debug)
|
||||||
|
|
||||||
self.notify = None
|
self.notify = None
|
||||||
|
|||||||
Reference in New Issue
Block a user