Team BBL
Previous Page Next Page

5.13. Temporary Files

The ISO C standard defines two functions that are provided by the standard I/O library to assist in creating temporary files.

#include <stdio.h>

char *tmpnam(char *ptr);

Returns: pointer to unique pathname

FILE *tmpfile(void);

Returns: file pointer if OK, NULL on error


The tmpnam function generates a string that is a valid pathname and that is not the same name as an existing file. This function generates a different pathname each time it is called, up to TMP_MAX times. TMP_MAX is defined in <stdio.h>.

Although ISO C defines TMP_MAX, the C standard requires only that its value be at least 25. The Single UNIX Specification, however, requires that XSI-conforming systems support a value of at least 10,000. Although this minimum value allows an implementation to use four digits (00009999), most implementations on UNIX systems use lowercase or uppercase characters.

If ptr is NULL, the generated pathname is stored in a static area, and a pointer to this area is returned as the value of the function. Subsequent calls to tmpnam can overwrite this static area. (This means that if we call this function more than once and we want to save the pathname, we have to save a copy of the pathname, not a copy of the pointer.) If ptr is not NULL, it is assumed that it points to an array of at least L_tmpnam characters. (The constant L_tmpnam is defined in <stdio.h>.) The generated pathname is stored in this array, and ptr is also returned as the value of the function.

The tmpfile function creates a temporary binary file (type wb+) that is automatically removed when it is closed or on program termination. Under the UNIX System, it makes no difference that this file is a binary file.

Example

The program in Figure 5.12 demonstrates these two functions.

If we execute the program in Figure 5.12, we get

   $ ./a.out
   /tmp/fileC1Icwc
   /tmp/filemSkHSe
   one line of output

Figure 5.12. Demonstrate tmpnam and tmpfile functions
#include "apue.h"

int
main(void)
{
    char    name[L_tmpnam], line[MAXLINE];
    FILE    *fp;

    printf("%s\n", tmpnam(NULL));       /* first temp name */

    tmpnam(name);                       /* second temp name */
    printf("%s\n", name);

    if ((fp = tmpfile()) == NULL)       /* create temp file */
        err_sys("tmpfile error");
    fputs("one line of output\n", fp);  /* write to temp file */
    rewind(fp);                         /* then read it back */
    if (fgets(line, sizeof(line), fp) == NULL)
        err_sys("fgets error");
    fputs(line, stdout);                /* print the line we wrote */

    exit(0);
}

The standard technique often used by the tmpfile function is to create a unique pathname by calling tmpnam, then create the file, and immediately unlink it. Recall from Section 4.15 that unlinking a file does not delete its contents until the file is closed. This way, when the file is closed, either explicitly or on program termination, the contents of the file are deleted.

The Single UNIX Specification defines two additional functions as XSI extensions for dealing with temporary files. The first of these is the tempnam function.

#include <stdio.h>

char *tempnam(const char *directory, const char
 *prefix);

Returns: pointer to unique pathname


The tempnam function is a variation of tmpnam that allows the caller to specify both the directory and a prefix for the generated pathname. There are four possible choices for the directory, and the first one that is true is used.

  1. If the environment variable TMPDIR is defined, it is used as the directory. (We describe environment variables in Section 7.9.)

  2. If directory is not NULL, it is used as the directory.

  3. The string P_tmpdir in <stdio.h> is used as the directory.

  4. A local directory, usually /tmp, is used as the directory.

If the prefix argument is not NULL, it should be a string of up to five bytes to be used as the first characters of the filename.

This function calls the malloc function to allocate dynamic storage for the constructed pathname. We can free this storage when we're done with the pathname. (We describe the malloc and free functions in Section 7.8.)

Example

The program in Figure 5.13 shows the use of tempnam.

Note that if either command-line argumentthe directory or the prefixbegins with a blank, we pass a null pointer to the function. We can now show the various ways to use it:

   $ ./a.out /home/sar TEMP                specify both directory and prefix
   /home/sar/TEMPsf00zi
   $ ./a.out " " PFX                       use default directory: P_tmpdir
   /tmp/PFXfBw7Gi
   $ TMPDIR=/var/tmp ./a.out /usr/tmp " "  use environment variable; no prefix
   /var/tmp/file8fVYNi                     environment variable overrides directory
   $ TMPDIR=/no/such/dir ./a.out /home/sar/tmp QQQ
   /home/sar/tmp/QQQ98s8Ui                 invalid environment directory is ignored

As the four steps that we listed earlier for specifying the directory name are tried in order, this function also checks whether the corresponding directory name makes sense. If the directory doesn't exist (the /no/such/dir example), that case is skipped, and the next choice for the directory name is tried. From this example, we can see that for this implementation, the P_tmpdir directory is /tmp. The technique that we used to set the environment variable, specifying TMPDIR= before the program name, is used by the Bourne shell, the Korn shell, and bash.

Figure 5.13. Demonstrate tempnam function
#include "apue.h"

int
main(int argc, char *argv[])
{
    if (argc != 3)
        err_quit("usage: a.out <directory> <prefix>");

    printf("%s\n", tempnam(argv[1][0] != ' ' ? argv[1] : NULL,
      argv[2][0] != ' ' ?  argv[2] : NULL));

    exit(0);
}

The second function that XSI defines is mkstemp. It is similar to tmpfile, but returns an open file descriptor for the temporary file instead of a file pointer.

#include <stdlib.h>

int mkstemp(char *template);

Returns: file descriptor if OK, 1 on error


The returned file descriptor is open for reading and writing. The name of the temporary file is selected using the template string. This string is a pathname whose last six characters are set to XXXXXX. The function replaces these with different characters to create a unique pathname. If mkstemp returns success, it modifies the template string to reflect the name of the temporary file.

Unlike tmpfile, the temporary file created by mkstemp is not removed automatically for us. If we want to remove it from the file system namespace, we need to unlink it ourselves.

There is a drawback to using tmpnam and tempnam: a window exists between the time that the unique pathname is returned and the time that an application creates a file with that name. During this timing window, another process can create a file of the same name. The tempfile and mkstemp functions should be used instead, as they don't suffer from this problem.

The mktemp function is similar to mkstemp, except that it creates a name suitable only for use as a temporary file. The mktemp function doesn't create a file, so it suffers from the same drawback as tmpnam and tempnam. The mktemp function is marked as a legacy interface in the Single UNIX Specification. Legacy interfaces might be withdrawn in future versions of the Single UNIX Specification, and so should be avoided.

    Team BBL
    Previous Page Next Page