加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

plain C:用fopen()打开一个目录

发布时间:2020-12-16 05:48:42 所属栏目:百科 来源:网络整理
导读:我有一个打开文件并检查其长度的程序. FILE* fd = fopen(argv[1],"rb");fseek(fd,SEEK_END);size_t flen = ftell(fd);if (flen == ((size_t)-1)) { printf("%s is a directory.n",argv[1]); fclose(fd); exit(1);} 现在,至少在Linux下,fopen()在打开目录时
我有一个打开文件并检查其长度的程序.
FILE* fd = fopen(argv[1],"rb");
fseek(fd,SEEK_END);
size_t flen = ftell(fd);
if (flen == ((size_t)-1)) {
    printf("%s is a directory.n",argv[1]);
    fclose(fd);
    exit(1);
}

现在,至少在Linux下,fopen()在打开目录时返回一个有效的文件描述符.这导致查找操作返回-1(或者,在64位系统上,size_t是无符号的,0xFFFFFFFFFFFFFFFF = 264-1).

不幸的是,上面代码中的条件(flen ==((size_t)-1))没有捕获到这种情况,flen == 0xFFFFFFFF(编辑:应该是0xFFFFFFFFFFFFFFFF)也没有. printf() – 将%x或%d作为格式字符串的命令显示比较的两侧应具有相同的值.

为什么比较运算符表现得如此奇怪,即使双方属于同一类型(size_t)?我使用gcc 4.8.1作为编译器.

解决方法

C99标准(或C2011标准)中不存在目录.因此,根据定义,打开目录可以是特定于实现的行为,也可以是未定义的行为.

fopen(3)可能失败(给出NULL结果). fseek(3)也可能失败(通过返回-1).然后你最好检查errno(3)或使用perror(3)

记录ftell返回长,-1L失败.在64位Linux上,这是0xffffffffffffffff.

你的代码应该是

FILE* fd = fopen(argv[1],"rb");
if (!fd) 
  { perror(argv[1]); exit(EXIT_FAILURE); };
if (fseek(fd,SEEK_END)<0) 
  { perror("fseek"); exit(EXIT_FAILURE); };
long flen = ftell(fd);
if (flen == -1L)
  { perror("ftell"); exit(EXIT_FAILURE); };

BTW,在带有libc-2.17和3.10.6内核的Linux / Debian / Sid / AMD64上,当argv [1]为/ tmp时,代码运行正常;令人惊讶的是,flen是LONG_MAX,即0x7fffffffffffffff

顺便说一句,在Linux上,目录是文件的特例.在文件路径上使用stat(2)(和file descriptor上的fstat,可能是从某些FILE *获得fileno(3)),以了解更多关于某个文件的元数据,包括其“类型”(通过其模式).你想要opendir(3),readdir(3)& closedir(3)对目录内容进行操作.另见inode(7).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读