feat(io): modernize sight::core::tools::System::getTemporaryFolder()
Description
getTemporaryFolder()
currently returns a path that link to a shared temporary folder managed by Sight that will be cleaned at application exit. However, most of the time, users want a clean private subfolder, especially in tests where having a pristine environment is required for reliability. Like in the real life, many people don't think about cleaning his own dish, even if the dish would not be used anymore.
Furthermore, there is a "zombie" cleaning mechanism, based on logging PID of the process who created the temporary file that is rather dangerous, especially in a multi-user OS. This can lead to strange and hard to find bugs.
The code in itself could also be simplified and made a bit safer by protecting against concurrent access (highly improbable, but could happen). We could also minimize path size which is problematic on Windows as currently 64 random chars are used to generate a random name + a prefix + the size of the subdir, often also random.
Proposal
- Use RAII to propose an auto-deleted directory / file.
- Remove dangerous stuff.
- Simplify code
Functional / Technical specifications
Will implement two classes: one for temporary directory, one for temporary file.
- Make use of RAII to clean up things at object destruction.
- Use a mutex for static operation (creation of the temporary root)
- For directory:
make use of std::tmpnam (yes it works now on Windows)until std::filesystem::create_directory returns true (meaning a new directory has been created). This should prevent race condition. - For file: almost the same but create an empty file, thus also preventing race condition.
- Provide also a stream version to eliminate potential security theat
class TemporaryDirectory
{
TemporaryDirectory()
{
// - Create or reuse a static "root" temporary directory (cleaned at application exit)
// - Create a garanted unique emtpy subdir (cleaned on destrcution), using the static root as parent
// - Throw an exception if we are not able to create the temporary directory
}
~TemporaryDirectory() noexcept
{
// - delete the created temporary directory
}
/// Returns the path of the temporary directory
const std::filesystem::path& scopedPath() const;
/// Returns the root path of all temporary directories.
static std::filesystem::path sharedPath();
}
class TemporaryFile
{
TemporaryFile()
{
// - Create or reuse a static "root" temporary directory (cleaned at application exit)
// - Create a garanted unique emtpy file (cleaned on destrcution), using the static root as parent
// - Throw an exception if we are not able to create the temporary file
}
~TemporaryFile() noexcept
{
// - delete the created temporary file
}
/// Returns the path of the temporary file. The file will be deleted at TemporaryFile destruction.
const std::filesystem::path& scopedPath() const;
/// Returns an unique temporary file path. The file will be deleted at application exit.
static std::filesystem::path uniquePath();
}
Test plan
- unit tests: new and existing one