Equivalent of mkdtemp()?

I need to create a temporary file, and I need to be able to control the file extension.

There’s the mktemp() on many platforms in C, but it doesn’t let me control the file extension. So I figured the next best thing would be to create a temporary directory and create my file inside that temporary directory. That means using the equivalent of mkdtemp(). But what is the equivalent of mkdtemp()?

I asked ChatGPT and it said to use std.fs.tempDir(), but that doesn’t seem to actually exist.

According to the manual on mktemp, it creates a directory with a generated name and gives it a permission of 0700 (read, write, & execute only for owner). Same for mkdtemp:

The mkdtemp() function generates a uniquely named temporary directory from template. The last six characters of template must be XXXXXX and these are replaced with a string that makes the directory name unique. The directory is then created with permissions 0700. Since it will be modified, template must not be a string constant, but should be declared as a character array.

To answer the question, the equivalent looks like making a directory with those same characteristics above (in both cases). I did a search for “temp” through the fs module and surrounding files and I’m not finding something that convincingly does what you’re looking for, but it’s not impossible to make something that acts similar using standard utilities.

I think this depends on your use case - are you in a situation where you can pick a name that won’t be used in your working directory? Something like “working_tmp_bla” or do you need it to be similar to the naming convention of mkdtemp?

2 Likes

Likewise, you could potentially link to C here and use those functions directly, too.

3 Likes

If you need the temporary directory for testing or building there are two zig library functions for that:

  1. std.testing.tmpDir usable when testing.
  2. std.Build.makeTempPath usable when building.

As @AndrewCodeDev said, if you are already link to the libc, you can use mkdtemp function directly.
Otherwise std.testing.tmpDir is a good starting point for your implementation (the required change is to define your parent directory, like /tmp instead of zig-cache/tmp).

1 Like

@Dimdin, one idea I had was using something like Random to fill in a byte buffer for the name. An obvious hitch here is that it can create characters that are illegal for directories/files. Replicating this behavior wouldn’t be terrible if OP doesn’t want to link to libc, but we’d need two things:

  1. Randomize a name for the path (or part of if we want to go the template route)
  2. Check if path exists - if so, re-randomize or overwrite based on a config

Yes, this is a nice strategy.

Where the directory is generated could be:

  • if environment variable TMP is defined and the TMP path exists then in TMP
  • if in windows then in environment variable TEMP
  • if in posix then in /tmp

The randomize and encoding of characters is already in the function that I mentioned.

pub fn tmpDir(opts: std.fs.Dir.OpenDirOptions) TmpDir {
    var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
    std.crypto.random.bytes(&random_bytes);
    var sub_path: [TmpDir.sub_path_len]u8 = undefined;
    _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
    ...

There must be some cleaning mechanism that erases everything in the directory and removes the directory. TmpDir handles this.

1 Like

Note that the canonical environment variable in Unix and POSIX is TMPDIR. See

1 Like