我有一个打开文件并检查其长度的程序.
FILE* fd = fopen(argv[1], "rb");
fseek(fd, 0, SEEK_END);
size_t flen = ftell(fd);
if (flen == ((size_t)-1)) {
printf("%s is a directory.\n", argv[1]);
fclose(fd);
exit(1);
}
Run Code Online (Sandbox Code Playgroud)
现在,至少在Linux下,fopen()在打开目录时返回有效的文件描述符.这导致查找操作返回-1(或者,如64位系统上的size_t无符号,0xFFFFFFFFFFFFFFFF= 2 64 -1).
不幸的是,上面的代码(flen == ((size_t)-1))中的条件没有捕获到这种情况,也没有flen == 0xFFFFFFFF(编辑:应该0xFFFFFFFFFFFFFFFF).printf()- 使用%xord %d作为格式字符串的命令显示比较的两侧应具有相同的值.
为什么比较运算符的行为方式如此奇怪,即使双方的类型相同(size_t)?我使用gcc 4.8.1作为编译器.
小智 8
来自http://pubs.opengroup.org/onlinepubs/7908799/xsh/fopen.html:
The fopen() function will fail if:
[EISDIR] The named file is a directory and mode requires write access.
Run Code Online (Sandbox Code Playgroud)
至少在Linux上,如果你试图fopen("dirname", "wb")得到EISDIR错误.我也试过一个带有d --------访问权限的目录,我仍然得到EISDIR(而不是EACCES.)
C99 标准(或 C2011 标准)中不存在目录。因此,根据定义,fopen-ing 目录要么是特定于实现的行为,要么是未定义的行为。
fopen(3)可能会失败(给出NULL结果)。fseek(3)也可能失败(通过返回 -1)。然后你最好检查errno(3)或使用perror(3)
ftell记录为返回long, 并-1L在失败时返回。在 64 位 Linux 上,这是0xffffffffffffffff.
你的代码应该是
FILE* fd = fopen(argv[1], "rb");
if (!fd)
{ perror(argv[1]); exit(EXIT_FAILURE); };
if (fseek(fd, 0, SEEK_END)<0)
{ perror("fseek"); exit(EXIT_FAILURE); };
long flen = ftell(fd);
if (flen == -1L)
{ perror("ftell"); exit(EXIT_FAILURE); };
Run Code Online (Sandbox Code Playgroud)
顺便说一句,在Linux / Debian的/ SID / AMD64用的libc-2.17和3.10.6内核,该代码运行时确定argv[1]的/tmp; 令人惊讶的flen是,LONG_MAX即0x7fffffffffffffff
顺便说一句,在 Linux 上,目录是文件的一种特殊情况。使用统计(2)文件路径(和fstat上一个文件描述符,也许得到的fileno(3)一些FILE*)了解一些文件的更多元数据,包括“类型”(直通其模式)。您希望opendir(3)、readdir(3)和closedir(3)对目录内容进行操作。另见inode(7)。
| 归档时间: |
|
| 查看次数: |
11058 次 |
| 最近记录: |