Ansi C和临时文件

时间:2014-09-10 07:29:50

标签: c c99 c89 gcc-pedantic

我需要来自临时文件的整数文件描述符才能在mmap中使用。如果在符合标准的情况下没有简单的方法可以做到这一点,则可能需要改变这种需求。

我最初使用:

获得了一个FILE流
FILE *tmpfile();

然后用...

int fileno(FILE foo);

一切都很好,直到我在fileno的手册页中注意到以下内容。

CONFORMING TO
   The functions clearerr(), feof(), and ferror() conform to C89 and C99.

fileno 不是c99的一部分。我已经在网上找了一个简单的方法来获取临时文件名或它的文件描述符,其方式在使用时不会抛出错误

-std=c99 -pedantic

到目前为止,我发现的最好的事情是:

http://www.di-mgt.com.au/c_function_to_create_temp_file.html

我很想知道其他人正在做些什么来解决这个问题,是否有一个我错过了某个地方的人工页面或者我可以在c99中使用的一些我忽略的东西?

更新:我写了一个小测试程序,看看我哪里出错了。请原谅我没有错误检查,我试图保持简短。我在Debian盒子上使用clang和gcc运行它:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/mman.h>

int main(int argc, const char* const argv[]) 
{   
  const char *fname = argv[1];
  /*  
   FILE *stream  = fopen("foo", "wb+");
   -std=c99 -pedantic fails on fileno
   int fd = fileno(stream);
  */
  int fd ;
  if((fd = open(fname, O_RDWR| O_CREAT, 0644)) < 0) {
    fprintf(stderr, "fd=%i, failed: %s\n",fd, strerror (errno));
    exit(EXIT_FAILURE);
  }   
  size_t fsize = 27; 
  char *buf;
  lseek (fd, fsize  - 1, SEEK_SET);
  write (fd, "", 1); 
  lseek (fd, 0, SEEK_SET);
  buf = mmap(0, fsize, PROT_WRITE, MAP_SHARED, fd, 0); 
  size_t i = 0;
  for(i = 0; i < fsize; i++) {
    buf[i] = i % 26 + 97; 
  }   
  buf[26] = '\n';
  munmap(buf, fsize);
  close(fd);
  return argc;//Avoid warnings about unused variables
} 

使用当心 rm -f 在命令开头使用clang或gcc运行它。

rm -f foo mmap; clang -Wall -Wextra -std=c99 -pedantic-errors -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition mmap.c -o mmap;./mmap foo;cat foo|wc -c

rm -f foo mmap; gcc   -Wall -Wextra -std=c99 -pedantic-errors -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition mmap.c -o mmap;./mmap foo;cat foo|wc -c

这有效意味着我错过了关于使用-std = c99 -pedantic的一些内容,因为当我试图包含任何非标准头文件时,我希望它会失败,即在这种情况下我会预料到错误试图包括这些......

#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

我有兴趣知道为什么上面的程序会编译,即标题中是否设置了关闭警告或者我是否滥用gcc?

2 个答案:

答案 0 :(得分:4)

你无法实现自己想要的目标。

-pedantic的文档说:

  

发出严格的ISO C和ISO C ++要求的所有警告;拒绝所有使用禁止扩展的程序,以及其他一些不遵循ISO C和ISO C ++的程序。对于ISO C,遵循由任何使用的-std选项指定的ISO C标准版本。

整数文件描述符不是C标准的一部分。他们来自POSIX。此外,C标准中没有mmap,它也来自POSIX。因此,-pedantic标志旨在让您无法执行您想要执行的操作。我刚检查了我的系统上的头文件和编译器配置,如果您正在使用gcc -std=c99 -pedantic进行编译,他们会明确排除(很多但不是全部)POSIX函数。

你确定你真的想要使用那面旗帜吗?

要创建标准C使用tmpfile的临时文件,而不是mmap,您需要使用普通freadfwrite来读取和写入文件。

答案 1 :(得分:0)

通过sort-bed,这是在fileName内使用临时文件名填充path指针并返回FILE*的一种方式:

FILE *
createTmpFile(char const* path, char** fileName)
{
  FILE* fp;
  int fd;
  char* tmpl;

  if (path == NULL)
      {
          fileName = NULL;
          return tmpfile();
      }

  tmpl = (char*)malloc(1 + strlen(path) + L_tmpnam);
  strcpy(tmpl, path);
  strcpy(tmpl+strlen(path), "/sb.XXXXXX");
  fd = mkstemp(tmpl);
  if(fd == -1)
      {
          fprintf(stderr, "unable to create temp file!\n");
          return NULL;
      }
  fp = fdopen(fd, "wb+");
  *fileName = (char*)malloc(strlen(tmpl) + 1);
  strcpy(*fileName, tmpl);
  free(tmpl);
  return fp;
}