Temporary file creation function

    The ISO C standard library provides two functions to help create temporary files.
#include <stdio.h>
char *tmpnam(char *ptr); /* Return value: pointer to unique pathname */
FILE *tmpfile(void); /* Return value: if successful, return the file pointer; otherwise, return NULL */

    The tmpnam function produces a valid pathname string that differs from an existing filename up to the number of invocations specified by TMP_MAX in <stdio.h>. If ptr is NULL, the generated pathname is stored in a static area, and a pointer to the static area is returned as the function value. Subsequent calls to tmpname will overwrite the static area, which means that if you call this function multiple times and you want to save the pathname, you should save a copy of the pathname, not the pointer. If ptr is not NULL, it is assumed to point to an array of at least L_tmpnam (in <stdio.h>) characters. Note that this function was marked as deprecated in SUSv4, but continues to be supported by the ISO C standard.
    tmpfile creates a temporary binary file (type wb+) that is automatically deleted when the file is closed or the program ends. The standard UNIX technique often used by this function is to call tmpnam to generate a unique pathname, then create a file with that pathname, and immediately unlink it. Because unlinking a file does not delete its contents, it is only when the file is closed, which can be explicit or automatically when the program terminates.
    The following program illustrates the application of these two functions.
#include <stdio.h>
#include <stdlib.h>

#define MAXLINE 4096

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){
		printf("tmpfile error\n");
		exit(1);
	}
	fputs("one line of output\n", fp);
	rewind(fp);              // read ti back
	if(fgets(line, sizeof(line), fp) == NULL){
		printf("fgets error\n");
		exit(1);
	}
	fputs(line, stdout);
    exit(0);
}

    The results are as follows:
$ ./tempfileDemo.out
/tmp/fileTOHsu6
/tmp/filekmAsYQ
one line of output

    The following two additional functions are defined in the Single UNIX Specification extension for processing temporary files, which are extensions to XSI.
#include <stdlib.h>
char *mkdtemp(char *template); /* Return value: if successful, return a pointer to the directory name; otherwise, return NULL */
int mkstemp(char *template); /* Return value: If successful, return the file descriptor; otherwise, return -1 */

    mkdtemp created a uniquely named directory with the permission set "S_IRUSR|S_IWUSR|S_IXUSR". Whereas mkstemp creates a file with a unique name, opens the file with the permission set "S_IRUSR|S_IWUSR", and does not delete the file automatically. Both functions create a directory or file through the template string, which is a path name with the last 6 digits set to "XXXXXX". The function replaces these placeholders with different strings to construct a unique pathname. If successful, both functions will modify the template string to reflect the name of the temporary file.
    Example of using the mkstemp function:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>

void make_temp(char *template);

int main(void){
	char	good_template[] = "/tmp/dirXXXXXX";		// right way
	char	*bad_tempfile = "/temp/dirXXXXXX";		// wrong way

	printf("trying to create first temp file...\n");
	make_temp(good_template);
	printf("trying to create seconde temp file...\n");
	make_temp(bad_tempfile);
	exit(0);
}

void make_temp(char *template){
	int fd;
	struct stat	sbuf;

	if((fd=mkstemp(template)) < 0){
		printf("can't create temp file");
		return;
	}
	printf("temp name = %s\n", template);
	close(fd);
	if(stat(template, &sbuf) < 0){
		if(errno == ENOENT)
			printf("file doesn't exist\n");
		else
			printf("stat failed\n");
	}else{
		printf("file exists\n");
		unlink(template);
	}
}

    Example of running result:
$ ./mkstempDemo.out
trying to create first temp file...
temp name = /tmp/dir0wPp4L
file exists
trying to create seconde temp file...
Segmentation fault (core dumped)
$

    The difference in the way the two template strings are declared leads to different results. Because the first template uses an array, the names are allocated on the stack. But the second uses a pointer, and only the pointer itself resides on the stack at this point. The compiler stores the string in the read-only section of the executable, and when the mkstemp function tries to modify the string, a segmentation fault occurs.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326174753&siteId=291194637