如何检测C文件流是否指向文件或串行设备?

时间:2014-03-21 18:32:51

标签: c unix file-io

我正在研究一种评估来自USB激光扫描仪数据的C应用程序,该激光扫描仪充当串行设备。出于测试目的,我还允许从文件中读取测试数据,因为始终连接扫描仪并不方便。

我像这样打开文件/设备:

FILE *fp = fopen(argv[1], "a+b");

根据我是否要从文件或设备中读取,我会传递文件路径或类似/dev/cu.usbmodemfd121(我在Mac上)。

只要我之前已经初始化了激光扫描仪,这种方法就可以正常工作,但我宁愿让我的应用程序这样做。但是,为了做到这一点,我必须首先弄清楚我是否正在从文件或设备中读取数据。 考虑到FILE *返回的fopen,我该怎么做?

我尝试使用fseek(fp, 1, SEEK_END)我希望扫描仪失败,因为它的流没有"结束"但是对于某些原因fseek不会失败..

2 个答案:

答案 0 :(得分:6)

您可以使用fileno获取文件描述符,然后对其执行fstat。它填充的struct stat包含类似st_mode的内容,它显示了fd的类型。我猜你的非文件设备S_ISCHR将是真的,或者至少S_ISREG将是假的。


如果您可以控制它,请不要执行fopen。直接使用open获取文件描述符,如果您真的需要C流,请使用fdopen

答案 1 :(得分:2)

@cnicutar的解决方案工作正常。这是我最终得到的,以防它帮助某人(清除错误检查):

#include <fcntl.h> /* open syscall */
#include <sys/stat.h>

int fd = -1;
int status;
FILE *fp = NULL;
struct stat fd_stat;
bool serial_device = false;

fd = open("/foo/bar/baz", O_RDONLY);
fp = fdopen(fd, "rb");
status = fstat(fd, &fd_stat);

printf("S_ISCHR: %d\n", S_ISCHR(fd_stat.st_mode));
printf("S_ISREG %d\n", S_ISREG(fd_stat.st_mode));

if(!S_ISREG(fd_stat.st_mode)) {
    serial_device = true;
}