Posix API:mkstemp, why it needs a char array as input.

Sometimes we need a temporary file to store data in our implementation. For development on linux platform, a convenient choice is writing a file under the folder /tmp. After reboot of OS, those files at least is not persist anymore. However, it needs more consideration to such a “temporary” file. For example, considering about uniqueness. It could be a bad idea that a hardcode file name for a program which could have multiple instances.

Here a useful system call is mkstemp().

#include <stdlib.h>
int mkstemp(char *template);
//Returns file descriptor on success, or –1 on error 

You can make a get a open file descriptor by call this function with given a char array (template)ended with 6 “X” and ‘\0’. For example:"/tmp/my_tempXXXXXX”. Here I must emphasize this pointer again, it should be a char array. Or it will cause segmentation fault if it received a char pointer to string literal. It could be confused for people. Why? Let us look few lines of ocde in posix source code as example.

Code : glibc/sysdeps/posix/tempname.c

...(skiped)
Int
__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
  int len;
  char *XXXXXX;
...(skiped)
/* This is where the Xs start.  */
XXXXXX = &tmpl[len - 6 - suffixlen];
/* Get some more or less random data.  */
RANDOM_BITS (value);
value ^= (uint64_t)__getpid () << 32;
for (count = 0; count < attempts; value += 7777, ++count)
  {
    uint64_t v = value;
    /* Fill in the random bits.  */
    XXXXXX[0] = letters[v % 62];
    v /= 62;
    XXXXXX[1] = letters[v % 62];
    v /= 62;
    XXXXXX[2] = letters[v % 62];
    v /= 62;
    XXXXXX[3] = letters[v % 62];
    v /= 62;
    XXXXXX[4] = letters[v % 62];
    v /= 62;
    XXXXXX[5] = letters[v % 62];
...(skiped)

Here *tmpl is the argument which is the given char array we talk above. A char array declared in our code should always located in the stack memory. And the data will be changed in this code by replacement with rundown bits. Finally it become the generated unique file name. If we call mkstemp() by giving it a pointer to string literal, it will absolutely cause a segmentation fault because the memory is located at DATA data segment. It is not changeable in the runtime.

Finally, it should connect to another system call unlink() which will delete a file with a filename. The common usage with mkstemp is involved about the char array which is changed. This two system calls cooperate together with the char array and control the life-cycle of the temporary file. As the following code block, you can see a example in the code.

From https://github.com/bladesu/linux_app_practice/blob/master/file_io/task_check_duplicated_fd.c

...(skiped)
    char template[] = "/tmp/tempXXXXXX";
    fd = mkstemp(template);
...(skiped, do something with mkstemp())
final:
...(skiped)
    if (template != NULL)
        unlink(template);

Complementary material

Temporary files: RAM or disk? :link

Reference

Section 5.12, The Linux Programming Interface.

comments powered by Disqus