在下面的代码中,我需要一个唯一的文件名,用它来做一些事情,并让它成为。它是关于将.class文件转换为二进制文件,让我们将其称为编译。
在隔离运行或一次完成3次时效果很好;但是,当我启动许多多个进程(例如7)时,我遇到了一些问题,其中我的一个或多个编译失败了。
这是代码:
#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;
}
环顾四周后,人们建议使用mkstemp()
;但是,正如您所看到的,我确实需要在几个地方使用文件名。
我试过调整这个,但一直遇到错误。我该如何安全地调整这种工作方法?
答案 0 :(得分:4)
来自mkstemp
int mkstemp(char *template);
mkstemp()函数从模板生成唯一的临时文件名,创建并打开文件,并返回文件的打开文件描述符。 模板的最后六个字符必须是&#34; XXXXXX&#34;这些都是 替换为使文件名唯一的字符串。 既然会 被修改,模板不能是字符串常量,但应该是 声明为字符数组。 使用权限0600创建文件,即读取和写入 仅限所有者。返回的文件描述符同时提供read和 写访问该文件。使用open(2)O_EXCL打开该文件 flag,保证调用者是创建调用者的进程 文件。
因此,如果您需要文件名,可以在传递给mkstemp的template
参数中找到它。