c-如何处理open()返回1



我编写了一个程序,创建一个空文本文件,如果成功,则打印Succeed

cc main.c编译

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
int main()
{
int fd;
// Create empty text file
fd = open("foo.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
assert(fd != -1);
fprintf(stderr, "File descriptor is %dn", fd);
printf("Succeedn");
}

使用./a.out运行时效果良好

当使用./a.out >&-运行时,open()返回1,我理解这一点。

但是,printf正在写入我的文件!

$ cat foo.txt
Succeed

我不想这样,所以我写了以下内容:

int main()
{
int fd1;
int fd2;
int fd3;
int fd4;
fd1 = open("foo.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
assert(fd1 != -1);
fd2 = open("foo.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
assert(fd2 != -1);
fd3 = open("foo.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
assert(fd3 != -1);
fd4 = open("foo.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
assert(fd4 != -1);
int final_fd = fd4;
close(fd1);
close(fd2);
close(fd3);
fprintf(stderr, "File descriptor is %dn", final_fd);
printf("Standard outputn");
}

它工作得很好,printf会失败并返回-1,但我不在乎。

我知道我可以通过检查open()返回值是否大于或等于3来进行优化,但这只是一个例子。

使用./a.out >/dev/null是有效的,但不是一个解决方案,我不能禁止我的程序的用户关闭标准输出。

这是处理这个问题的正确方法吗?

在POSIX上,open将始终返回最小的可用文件描述符。处理此问题的唯一方法是在程序开始时检查文件描述符0。。。2例如使用isatty-如果isatty返回0并且errno设置为EBADF,则文件描述符未使用,然后应该从/dev/null:打开一个新的描述符

for (int fd = 0; fd <= 2; fd++) {
errno = 0;
if (! isatty(fd) && errno == EBADF) {
open("/dev/null", O_RDWR);
}
}

请注意,这些流未打开的状态根本不符合标准。C11 7.21.3p7:

7在程序启动时,三个文本流是预定义的,不需要显式打开——标准输入(用于读取常规输入)、标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。在最初打开时,标准错误流没有被完全缓冲;当且仅当可以确定流不涉及交互式设备时,标准输入流和标准输出流被完全缓冲。

这可能被认为是C启动例程中的失败——在我看来,它应该至少向/dev/null打开这些流


尽管现在我尝试了这一点,但我已经得出结论,在关闭标准流的情况下运行程序不仅会大脑受损,而且会完全脑死亡,因为任何fopen也会在stdinstdoutstderr上打开,所以我会将代码修改为:

struct stat statbuf;
for (int fd = 0; fd <= 2; fd++) {
if (fstat(fd) == 0 && errno == EBADF) {
fprintf(stderr, "Id10t error: closed standard IO descriptor %dn", fd);
abort();
}
}

相关内容

  • 没有找到相关文章

最新更新