5.13. Temporary FilesThe ISO C standard defines two functions that are provided by the standard I/O library to assist in creating temporary files.
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>.
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. ExampleThe 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.
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.
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.) ExampleThe 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.
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.
|