tempfile
                                
                                 tempfile copied to clipboard
                                
                                    tempfile copied to clipboard
                            
                            
                            
                        extend NamedTemporaryFile to support persisting securely created files
Linux supports linking a securely created temporary file (O_TMPFILE) back into the filesystem, so long as it wasn't created with O_EXCL. I believe this will improve the performance (and security) of one of my applications.
This branch extends NamedTemporaryFile to create these unnamed temporary files, such that the existing interface is maintained: you can persist these unnamed NamedTemporaryFiles into the filesystem:
let tmp = NamedTempFile::new_deleted(&temp_dir).unwrap();
...
tmp.persist_noclobber(&some_directory).unwrap();
The code hasn't turned out that great:
- I don't like the name new_deleted, norattempt_without_name, nor ramming this support for unnamed temporary files into an interface namedNamedTemporaryFile. I decided to add it toNamedTemporaryFileas it is where thepersistfunctionality currently exists, and because we can gracefully fall-back to a real named file without breaking anyone, hopefully.
- The path()function continues to exist, and returns an implementation detail: the path to the/proc/self/fd... While not inherently harmful, this is at least confusing.
- I cannot see how to renameat2directly into the filesystem, so for thepersist-clobbering case, the code has to create yet another named temporary file, and link into that, then rename. This is horrible.
- I haven't tested it on non-Linux, and suspect I've made some mistakes there.
Note that NamedTemporaryFiles can't end up marked as deleted on non-modern-linux platforms, so the error handling/fallback around those cases is less interesting (e.g. the bailing in the windows persist implementation).
So:
- Should this functionality belong in this create?
- Can anyone else think of a better interface or name?
- Is there anything horribly wrong with what's here?
The CI failures are about the use of inline #[cfg.. in 1.9.0, which I'm too lazy to remove at this stage; it passes fine on stable, beta and nightly, and is relatively trivial to fix for real.
This really doesn't belong in NamedTemporaryFile. Originally, I had a separate TempFile type for unnamed temporary files and planned on adding this feature to them. Unfortunately, I then learned that BSD derivatives (including MacOS) don't support operations like this so I gave up ( :disappointed:).
While not inherently harmful, this is at least confusing.
It's a bit more than that given that /proc/self/fd/... is:
- Process specific. Even if we use /proc/$pid/fd/..., this path isn't guaranteed to work, e.g., across PID namespaces.
- A fake symlink.
So, I'd really like this feature but this is definitely not the right place to put it and I don't really know of the right, cross-platform way to do this (or even if it's possible).
I've been thinking about this.
I don't think it can be done in a platform agnostic way (yet!). As such, I don't think exposing a new interface, which you have to pick to use on Linux if you want performance/security, is the right way to go.
How about making path() panic for deleted files (on all platforms)? This doesn't change the API, and doesn't break any existing code, only people who opt-in to this new functionality.
My aim is really to have the performance benefit on Linux, but silently fallback to the alternative if it's unsupported, which really does feel like the job of NamedTemporaryFile.
Having a method which returns two different implementations could be made transparent, and only expose the bits of the API that actually work well generically? I'm not really feeling it.
enum MaybeFastPersistableTemporaryFile {
   Fast(RawFd),
   Classic(NamedTemporaryFile),
}
impl AsRef<File> for MaybeFastPersistableTemporaryFile { ... }
impl MaybeFastPersistableTemporaryFile {
  fn persist_noclobber(..) { ... }
}
How about making path() panic for deleted files (on all platforms)?
The point of named temporary files is for them to be named. That's why I'm not a fan of adding a deleted constructor to the NamedTempFile interface and why I suggested adding a different type (one for persistable but unnamed temporary files).
However, it is always possible for NamedTempFiles to be deleted later anyways and using O_TMPFILE would actually be more reliable in this case because /proc/$PID/fd/$FD can't be deleted (without closing the file)...
I'll have to think about this.
So, after thinking about this, I'm really not convinced it's worth it. The primary goal of this library is to be completely cross-platform and abstract away all the platform-specific nonsense one usually runs into when dealing with temporary files so I'd rather not add any platform-specific features.