Open nyanpasu64 opened 3 years ago
Hey @nyanpasu64 thanks a lot for your extensive research and contribution ! Do you think you could publish #44 as a library instead and have handlr simply use it ?
If you want to take the easy way out, you can just use the upstream atomicwrites library, and if they add support for disabling fsync on directory, you can add that as an optimization later. I think that's a better outcome than me publishing a new crate solely serving as an edited version of atomicwrites that only works on Linux.
I think it makes sense to atomically write to mimeapps.list, by writing to a temporary file, then renaming it on top of mimeapps.list.
https://danluu.com/file-consistency/ describes the pitfalls of filesystems and fsync. It describes using log files for atomicity, and advises against rename-based atomic saves. However, rename-based saving is our only option, since apps don't know how to read log files but only mimeapps.list. And GLib uses rename and fsync, so it should be fine...
G_FILE_SET_CONTENTS_CONSISTENT
(create temporary file, fsync the temp file, then rename). Does not passG_FILE_SET_CONTENTS_DURABLE
(fsync the directory after renaming). I agree with these choices.G_FILE_SET_CONTENTS_ONLY_EXISTING
(don't write to a temp file if the file if it doesn't exist yet). I disagree with this choice, because it only improves performance in the rare situation where mimeapps.list doesn't exist at all, but introduces an edge case where a corrupted file can be written to disk or read by another app, and the exact reason why is hard to diagnose.You can implement atomic saving yourself, or shell out to a crate like atomicwrites or tempfile's
persist
method (not sure why there are two of them, link, link). Note that tempfile's persist method mentions the risk of the tempfile being deleted or replaced with a different file under the same name. I haven't researched the best approach to take, the crate options out there, or where to create a temp file, or the optimal syscall for renaming. (capnproto's kj filesystem library creates a temporary file in the same directory and usesrenameat()
.)