How to create a temporary directory in C++?
Asked Answered
I

6

16

I'm writing a function in C++ which creates a temporary directory. Such function should be as most portable as possible, e.g. it should work under linux, mac and win32 environments. How do I achieve that?

Illdefined answered 31/7, 2010 at 22:5 Comment(3)
Standard C++ has no directory manipulation functions.Pitarys
The POSIX standard does have a definition. All modern OS have a POSIX compliance layer (including windows). So the mktemp() family of functions is what you are looking for. But be careful it is a security vulnerability to create a temp directory then place files in it. It is more secure to create file descriptors directly.Goldfish
What about getenv() passing "TMP"?Illdefined
W
8

Check the mkdtemp function here.

Wrongly answered 31/7, 2010 at 22:12 Comment(3)
This doesn't exist on Windows, as far as I know. :(Consensus
there is no platform independent way to do it in standard c/c++, use GetTempPath and GetTempFileName on WindowsHiltan
use tmpnam(), it is portable.Six
O
22

Version 3 of Boost Filesystem Library provides function unique_path() for generating a path name suitable for creating a temporary file or directory.

using namespace boost::filesystem;

path ph = temp_directory_path() / unique_path();
create_directories(ph);
Olson answered 13/5, 2011 at 7:37 Comment(0)
P
12

C++17 std::filesystem::temp_directory_path + random number generation

Here is a pure C++17 solution that might be reliable: no Boost or other external libraries and no mkdtemp which is POSIX.

We just loop over random numbers until we are able to create a directory that did not exist before inside std::filesystem::temp_directory_path (/tmp in Ubuntu 18.04).

We can then explicitly remove the created directory with std::filesystem::remove_all after we are done with it.

I'm not sure that the C++ standard guarantees this, but is extremely likely that std::filesystem::temp_directory_path calls mkdir, which atomically tries to create the directory and if it can't fails with EEXIST, so I don't think there can be race conditions across parallel callers.

main.cpp

#include <exception>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>

#include <filesystem>

std::filesystem::path create_temporary_directory(
      unsigned long long max_tries = 1000) {
    auto tmp_dir = std::filesystem::temp_directory_path();
    unsigned long long i = 0;
    std::random_device dev;
    std::mt19937 prng(dev());
    std::uniform_int_distribution<uint64_t> rand(0);
    std::filesystem::path path;
    while (true) {
        std::stringstream ss;
        ss << std::hex << rand(prng);
        path = tmp_dir / ss.str();
        // true if the directory was created.
        if (std::filesystem::create_directory(path)) {
            break;
        }
        if (i == max_tries) {
            throw std::runtime_error("could not find non-existing directory");
        }
        i++;
    }
    return path;
}

int main() {
    auto tmpdir = create_temporary_directory();
    std::cout << "create_temporary_directory() = "
              << tmpdir
              << std::endl;

    // Use our temporary directory: create a file
    // in it and write to it.
    std::ofstream ofs(tmpdir / "myfile");
    ofs << "asdf\nqwer\n";
    ofs.close();

    // Remove the directory and its contents.
    std::filesystem::remove_all(tmpdir);
}

GitHub upstream.

Compile and run:

g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp -lstdc++fs
./main.out

Sample output:

_directory.out
temp_directory_path() = "/tmp"
create_temporary_directory() = "/tmp/106adc08ff89874c"

For files, see: How to create a temporary text file in C++? Files are a bit different because open in Linux has the O_TMPFILE, which creates an anonymous inode that automatically disappears on close, so dedicated temporary file APIs can be more efficient by using that. There is no analogous flag for mkdir however, so this solution might be optimal.

Tested in Ubuntu 18.04.

Princessprinceton answered 18/10, 2019 at 16:36 Comment(0)
W
8

Check the mkdtemp function here.

Wrongly answered 31/7, 2010 at 22:12 Comment(3)
This doesn't exist on Windows, as far as I know. :(Consensus
there is no platform independent way to do it in standard c/c++, use GetTempPath and GetTempFileName on WindowsHiltan
use tmpnam(), it is portable.Six
L
1

Boost's Filesystem library provides platform-independent directory functions. It will increase your program size a bit, but using Boost is often better (and often easier) than rolling your own.

http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm

Lentha answered 1/8, 2010 at 3:8 Comment(1)
I don't want to introduce dependency on boost just for that.Illdefined
P
0

mkdtemp(char *template)

http://www.cl.cam.ac.uk/cgi-bin/manpage?3+mkdtemp

Creates a temporary directory.

Phosphorylase answered 31/7, 2010 at 22:7 Comment(1)
I followed your documentation link. It only describes how to create a temporary file. What was asked for is how to create a temporary directory.Lakendra
C
0

There's no standard function to do this, so you'll need to compile different implementations for each platform you target.

On Windows, for example, you should use the temp directory, which can be obtained by a call to GetTempPath().

Consensus answered 1/8, 2010 at 2:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.