C 如何创建一个临时文件名';并发执行安全吗?
在下面的代码中,我需要一个唯一的文件名,用它做一些事情,然后就这样吧。它是关于将.class文件转换为二进制文件的,我们称之为编译 当单独运行或一次运行3次时,它工作正常;但是,当我启动多个进程(例如7个进程)时,我遇到了一些问题,其中一个或多个编译失败 代码如下:C 如何创建一个临时文件名';并发执行安全吗?,c,linux,temporary-files,C,Linux,Temporary Files,在下面的代码中,我需要一个唯一的文件名,用它做一些事情,然后就这样吧。它是关于将.class文件转换为二进制文件的,我们称之为编译 当单独运行或一次运行3次时,它工作正常;但是,当我启动多个进程(例如7个进程)时,我遇到了一些问题,其中一个或多个编译失败 代码如下: #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> static unsign
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
static unsigned int numFiles = 0;
static unsigned long numBytes = 0;
FILE* rawf;
char* raw_file_name_end = ".raw_ujc";
char * rawfilename;
static void byte(unsigned char v){
if(numBytes) printf(", ");
printf((numBytes & 0x0F) ? "0x%02X" : "\n\t0x%02X", v);
fwrite(&v,sizeof(v),1,rawf);
numBytes++;
}
int main(int argc, char** argv){
const char* self = argv[0];
int c;
const char* classCvt = 0;
long len;
if(argc == 1){
fprintf(stderr, "USAGE: %s [-c <path_to_classCvt>] <file 1> [<file 2> [ <file 3> [...]]] > result.c\n", self);
return -1;
}
argv++;
argc--;
if(argv[0][0] == '-' && argv[0][1] == 'c' && !argv[0][2]){
classCvt = argv[1];
argv += 2;
argc -= 2;
}
printf("\nService optimized bytecode = {\n\t");
while(argc--){
char* filename = *argv;
rawfilename = malloc(sizeof(char) * (strlen(filename)-strlen(".class")) + sizeof(char) * strlen(raw_file_name_end)+1);
strncpy(rawfilename,filename,(strlen(filename)-strlen(".class")));
strcat(rawfilename,raw_file_name_end);
fprintf(stderr, "rawfilename after alloc: %s \n", rawfilename);
if(classCvt){
char* t;
filename = tempnam(NULL, NULL);
if(!filename){
fprintf(stderr, "%s: failed to create a tempfile: %d\n", self, errno);
return -10;
}
t = malloc(strlen(filename) + strlen(classCvt) + strlen(*argv) + 32);
if(!t){
fprintf(stderr, "%s: failed to alloc a small string. This is unlikely\n", self);
free(t);
return -11;
}
sprintf(t, "%s < %s > %s", classCvt, *argv, filename);
if(system(t)){
fprintf(stderr, "%s: system() fail: %d\n", self, errno);
free(t);
return -12;
}
free(t);
}
printf("filename is %s\n",filename);
FILE* f = fopen(filename, "r");
rawf = fopen(rawfilename, "wb");
if(filename != *argv){
unlink(filename);
free(filename);
}
if(!f){
fprintf(stderr, "%s: failed to open '%s': %d\n", self, *argv, errno);
fclose(f);
return -2;
}
if(!f){
fprintf(stderr, "%s: failed to open '%s': %d\n", self, *argv, errno);
fclose(f);
return -2;
}
if(fseek(f, 0, SEEK_END)){
fprintf(stderr, "%s: failed to seek(1) in '%s': %d\n", self, *argv, errno);
fclose(f);
return -3;
}
len = ftell(f);
if(len < 0){
fprintf(stderr, "%s: failed to tell in '%s': %d\n", self, *argv, errno);
fclose(f);
return -4;
}
if(fseek(f, 0, SEEK_SET)){
fprintf(stderr, "%s: failed to seek(2) in '%s': %d\n", self, *argv, errno);
fclose(f);
return -5;
}
if(len > 0x00FFFFFFUL){
fprintf(stderr, "%s: file '%s' is %lu bytes, while maximum allowable size is %lu.\n", self, *argv, len, 0x00FFFFFFUL);
fclose(f);
return -6;
}
byte(len >> 16);
byte(len >> 8);
byte(len);
while((c = fgetc(f)) != EOF){
byte(c);
}
numFiles++;
fclose(f);
fclose(rawf);
argv++;
}
byte(0);
byte(0);
byte(0);
printf("\n};\n");
fprintf(stderr, "%s: processed %u files, producing %lu (0x%lX) bytes of output\n", self, numFiles, numBytes, numBytes);
fprintf(stderr, "rawfilename at end: %s \n", rawfilename);
free(rawfilename);
return 0;
}
#包括
#包括
#包括
#包括
静态无符号整数文件=0;
静态无符号长字节数=0;
文件*rawf;
char*raw_file_name_end=“.raw_ujc”;
char*rawfilename;
静态空字节(无符号字符v){
如果(单位)为printf(“,”);
printf((numBytes&0x0F)-“0x%02X”:“\n\t0x%02X”,v);
fwrite(&v,sizeof(v),1,rawf);
numBytes++;
}
int main(int argc,字符**argv){
常量字符*self=argv[0];
INTC;
常量字符*classCvt=0;
龙伦;
如果(argc==1){
fprintf(stderr,“用法:%s[-c][[…]]]]>result.c\n”,self);
返回-1;
}
argv++;
argc--;
如果(argv[0][0]='-'&&argv[0][1]=='c'&&&!argv[0][2]){
classCvt=argv[1];
argv+=2;
argc-=2;
}
printf(“\n服务优化字节码={\n\t”);
而(argc--){
char*filename=*argv;
rawfilename=malloc(sizeof(char)*(strlen(filename)-strlen(“.class”))+sizeof(char)*strlen(raw\u file\u name\u end)+1;
strncpy(rawfilename,filename,(strlen(filename)-strlen(“.class”));
strcat(原始文件名、原始文件名、原始结束);
fprintf(stderr,“分配后的rawfilename:%s\n”,rawfilename);
if(类别CVT){
char*t;
filename=tempnam(NULL,NULL);
如果(!filename){
fprintf(stderr,“%s:未能创建临时文件:%d\n”,self,errno);
返回-10;
}
t=malloc(strlen(文件名)+strlen(classCvt)+strlen(*argv)+32);
如果(!t){
fprintf(stderr,“%s:分配小字符串失败。这不太可能\n”,self);
自由(t);
返回-11;
}
sprintf(t,“%s<%s>%s”,classCvt,*argv,文件名);
if(系统(t)){
fprintf(stderr,“%s:system()失败:%d\n”,self,errno);
自由(t);
返回-12;
}
自由(t);
}
printf(“文件名为%s\n”,文件名);
文件*f=fopen(文件名,“r”);
rawf=fopen(rawfilename,“wb”);
如果(文件名!=*argv){
取消链接(文件名);
免费(文件名);
}
如果(!f){
fprintf(stderr,“%s:无法打开“%s”:%d\n,self,*argv,errno);
fclose(f);
返回-2;
}
如果(!f){
fprintf(stderr,“%s:无法打开“%s”:%d\n,self,*argv,errno);
fclose(f);
返回-2;
}
if(fseek(f,0,SEEK_END)){
fprintf(stderr,“%s:在“%s”中查找(1)失败:%d\n”,self,*argv,errno);
fclose(f);
返回-3;
}
len=ftell(f);
if(len<0){
fprintf(stderr,“%s:在“%s”中告知失败:%d\n”,self,*argv,errno);
fclose(f);
返回-4;
}
if(fseek(f,0,SEEK_SET)){
fprintf(stderr,“%s:在“%s”中查找(2)失败:%d\n”,self,*argv,errno);
fclose(f);
返回-5;
}
如果(len>0x00FFFFFFUL){
fprintf(stderr,“%s:文件“%s”为%lu字节,而允许的最大大小为%lu。\n”,self,*argv,len,0x00FFFFFFUL);
fclose(f);
返回-6;
}
字节(len>>16);
字节(len>>8);
字节(len);
而((c=fgetc(f))!=EOF){
字节(c);
}
numFiles++;
fclose(f);
fclose(rawf);
argv++;
}
字节(0);
字节(0);
字节(0);
printf(“\n};\n”);
fprintf(stderr,“%s:处理了%u个文件,产生了%lu(0x%lX)字节的输出\n”,self,numFiles,numBytes,numBytes);
fprintf(stderr,“末尾的rawfilename:%s\n”,rawfilename);
免费(rawfilename);
返回0;
}
环顾四周后,人们建议使用mkstemp()
;但是,正如您所看到的,我确实需要在几个地方使用文件名
我试着调整这个,但总是出错。如何安全地调整此工作方法?来自
mkstemp
int mkstemp(char *template);
函数的作用是:从模板生成一个唯一的临时文件名,创建并打开文件,并返回文件的打开文件描述符。
模板的最后六个字符必须是“XXXXXX”,并且
替换为使文件名唯一的字符串因为它会
若要修改,模板不能是字符串常量,但应为
声明为字符数组。
该文件是以0600权限创建的,即读加写权限
仅供业主使用。返回的文件描述符提供读和写操作
对文件的写访问权限。文件是用open(2)O_EXCL打开的
标志,保证调用方是创建
文件
因此,如果需要文件名,可以在传递给mkstemp的
模板
参数中找到它。来自mkstemp的手册页
int mkstemp(char *template);
函数的作用是:从模板生成一个唯一的临时文件名,创建并打开文件,并返回文件的打开文件描述符。
模板的最后六个字符必须是“XXXXXX”,并且
替换为使文件名唯一的字符串因为它会
若要修改,模板不能是字符串常量,但应为
声明为字符数组。
该文件是以0600权限创建的,即读加写权限