临时文件创建函数

    ISO C 标准库提供了两个函数以帮助创建临时文件。
#include <stdio.h>
char *tmpnam(char *ptr);    /* 返回值:指向唯一路径名的指针 */
FILE *tmpfile(void);     /* 返回值:若成功,返回文件指针;否则,返回 NULL */

    tmpnam 函数产生一个与现有文件名不同的一个有效路径名字符串,其最多调用次数由 <stdio.h> 中的 TMP_MAX 来指定。若 ptr 是 NULL,则产生的路径名存放在一个静态区中,指向该静态区的指针作为函数值返回。后续再调用 tmpname 时会重写该静态区,这意味着如果调用此函数多次,而且想保存路径名,则应该保存路径名的副本,而非指针的副本。若 ptr 不是 NULL,则认为它应该是指向至少 L_tmpnam(在 <stdio.h> 中)个字符的数组。注意,该函数在 SUSv4 中被标记为弃用,但 ISO C 标准仍继续支持。
    tmpfile 创建一个临时二进制文件(类型为 wb+),在关闭该文件或程序结束时将自动删除这种文件。该函数经常使用的标准 UNIX 技术是先调用 tmpnam 产生一个唯一的路径名,然后再用该路径名创建一个文件,并立即 unlink 它。因为对一个文件解除链接并不删除其内容,要关闭该文件时才会,而关闭文件可以是显式的,也可以在程序终止时自动进行。
    下列程序说明了这两个函数的应用。
#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);
}

    运行结果如下:
$ ./tempfileDemo.out
/tmp/fileTOHsu6
/tmp/filekmAsYQ
one line of output

    Single UNIX Specification 扩展中为处理临时文件定义了下面另外两个函数,它们是 XSI 的扩展部分。
#include <stdlib.h>
char *mkdtemp(char *template);  /* 返回值:若成功,返回指向目录名的指针;否则,返回 NULL */
int mkstemp(char *template);  /* 返回值:若成功,返回文件描述符;否则,返回 -1 */

    mkdtemp 使用权限集“S_IRUSR|S_IWUSR|S_IXUSR”创建了一个具有唯一名字的目录。而 mkstemp 创建一个具有唯一名字的文件,并以权限集“S_IRUSR|S_IWUSR”打开该文件,另外也不会自动删除该文件。这两个函数都是通过 template 字符串来创建目录或文件的,该字符串是后 6 位设置为“XXXXXX”的路径名,函数将这些占位符替换成不同的字符串来构建一个唯一的路径名。如果成功,这两个函数都将修改 template 字符串以反映临时文件的名字。
    mkstemp 函数使用示例:
#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);
	}
}

    运行结果示例:
$ ./mkstempDemo.out 
trying to create first temp file...
temp name = /tmp/dir0wPp4L
file exists
trying to create seconde temp file...
段错误 (core dumped)
$ 

    两个模板字符串声明方式的不同带来了不同的运行结果。因为第一个模板使用了数组,名字是在栈上分配的。但第二个使用了指针,此时只有指针自身驻留在栈上。编译器把字符串存放在可执行文件的只读段,当 mkstemp 函数试图修改该字符串时,就会出现段错误。

猜你喜欢

转载自aisxyz.iteye.com/blog/2388250
今日推荐