我正在用C编写学校作业,在文件系统中搜索目录,常规文件和符号链接.现在我lstat用来获取有关物品的信息.
因此,whats的区别lstat fstat和stat系统调用?
我正在使用C++ fstream来读取配置文件.
#include <fstream>
std::ifstream my_file(my_filename);
Run Code Online (Sandbox Code Playgroud)
现在,如果我传递一个目录的路径,它会默默地忽略它.my_file.good()即使my_filename是目录,Eg 也会返回true .由于这是我的程序的意外输入,我喜欢检查它,并抛出异常.
如何检查刚打开的fstream是否是常规文件,目录或流?
我似乎无法找到一种方法:
在一些论坛讨论中,有人认为这两者都不可能,因为这是依赖于操作系统的,因此永远不会成为fstream C++标准的一部分.
我能想到的唯一选择是重写我的代码以完全摆脱ifstream并使用文件描述符(*fp)的C方法,以及fstat():
#include <stdio.h>
#include <sys/stat.h>
FILE *fp = fopen(my_filename.c_str(), "r");
// skip code to check if fp is not NULL, and if fstat() returns != -1
struct stat fileInfo;
fstat(fileno(fp), &fileInfo);
if (!S_ISREG(fileInfo.st_mode)) {
fclose(fp);
throw std::invalid_argument(std::string("Not a regular file ") + my_filename);
}
Run Code Online (Sandbox Code Playgroud)
我更喜欢fstream.因此,我的问题.
如果我有一个已知的文件描述符打开的文件,什么是使用的优点fstat(),对stat()?为什么不只有一个功能?
int fstat(int fildes, struct stat *buf)
int stat(const char *path, struct stat *buf)
Run Code Online (Sandbox Code Playgroud) 我已经处理了几个星期的问题,现在更新需要独立于系统的20年代码(适用于Linux和Windows).它涉及检查时间,使用时间(TOCTOU)问题.我在这里做了一个帖子,但它没有走得太远,经过一段时间的反复思考并深入研究这个问题,我想我更好地理解了我的问题.也许我可以再问一下......
根据我的阅读,代码需要检查文件是否存在,是否可访问,打开文件,执行某些操作,最后关闭文件.似乎最好的方法是调用lstat(),调用fopen(),调用fstat()(以排除TOCTOU),然后执行操作并关闭文件.
但是,我一直认为lstat()并且fstat()是POSIX定义的,而不是 C标准定义的,排除了它们用于系统不可知程序的用法,同样open()不应该用于交叉兼容性.你会如何实现这个?
如果你看看我的第一篇文章,你可以看到20年前的开发人员使用C预处理器将代码切换成交叉兼容的部分,但即使我这样做,我也不知道要替换什么lstat()或者fstat()用什么(他们的windows同行).
编辑:为此帖添加了相关代码; 如果有什么不清楚请转到原始帖子
#ifdef WIN32
struct _stat buf;
#else
struct stat buf;
#endif //WIN32
FILE *fp;
char data[2560];
// Make sure file exists and is readable
#ifdef WIN32
if (_access(file.c_str(), R_OK) == -1) {
#else
if (access(file.c_str(), R_OK) == -1) {
#endif //WIN32
char message[2560];
sprintf(message, "File '%s' Not Found or Not Readable", file.c_str()); …Run Code Online (Sandbox Code Playgroud) 标题说明了一切:可以使用stat() 之后 fopen()避免使用时间(TOCTOU)竞争条件吗?
一些细节:
我正在编写一个只读取文件的C程序,但在被要求读取目录时需要正确错误.截至目前,它使用open()(与O_RDWR),以产生一个错误,然后检查errno为EISDIR,像这样:
int fd = open(path, O_RDWR);
if (fd == -1) {
if (errno == EISDIR) return PATH_IS_DIR;
else return FILE_ERR;
}
Run Code Online (Sandbox Code Playgroud)
上述解决方案的问题是该程序只需要读取文件,因此通过打开文件O_RDWR,如果用户具有读取权限,但可能错误地获取权限错误,而不是写入权限.
是否可以采取以下措施以避免TOCTOU竞争条件?
struct stat pstat;
FILE *f = fopen(path, "r");
if (!f) return FILE_ERR;
if (stat(path, &pstat) == -1) {
fclose(f);
return FILE_ERR;
}
if (S_ISDIR(pstat.st_mode)) {
fclose(f);
return PATH_IS_DIR;
}
Run Code Online (Sandbox Code Playgroud)
如果不可能,是否有其他解决方案可以防止TOCTOU错误以及错误的权限错误?
我想使用 boost::filesystem 从文件中获取所有者和组,但从未找到任何方法来做到这一点。
我可以获得文件的权限,但由于我不知道文件的所有者,这没有任何意义。
我找到了 posix fstat 函数,但我再次想使用 boost 或另一个 C++ 库而不是 C 函数。
我以为我理解fstat,我错了.
我需要知道文件的大小,然后从文件中读取.
fileN 具有文件的路径和文件的名称.看起来像这样.0.txt
struct stat fileStat;
FILE *fp;
int fd = 0;
int i;
for(i = 0; i < 100; i++)
{
fp = fopen(fileN, "r");
fd = open(fileN, "r"); // I think this is eating my files and making them 0 size.
fstat(fd, $fileStat);
printf("%d", fileStat.st_size);
fclose(fp);
}
Run Code Online (Sandbox Code Playgroud)
为什么我需要使用fd = open(fileN, "r");使用fstat?感觉就像我打开文件两次.
如果fileStat是一个结构,为什么我使用fileStat.st_size而不是fileStat->st_size像我创建自己的结构时那样?示例:myString->characters;
为什么上面的代码在printf执行时会打印0 ?是的,文件的大小大于0,我有正确的文件名和路径.
上面的所有代码都是我对Googled代码的解释,并与我的试错实现混合在一起.这就是我有这么多问题的原因.
编辑:解决方案:open()被调用错误并影响文件.
如何获取系统中当前的文件描述符数?
我知道如何获得最大值.
% sysctl kern.maxfiles
kern.maxfiles: 8232
Run Code Online (Sandbox Code Playgroud)
参考:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
struct stat buf;
int fd;
if (fd = open(argv[1], O_RDWR | O_CREAT)<0)
{
printf("file open error\n");
return 1;
}
if (link(argv[1], "link1") + link(argv[1], "link2")<0)
{
printf("error link\n");
return 1;
}
if (fstat(fd, &buf)<0)
{
printf("error fstat\n");
return 1;
}
printf("nlinks before = %d \n", buf.st_nlink);
if (unlink("link2") + unlink("link1") + unlink(argv[1])<0)
{
printf("unlink error\n");
return 1;
}
if (fstat(fd, &buf)<0)
{
printf("error fstat\n");
return …Run Code Online (Sandbox Code Playgroud)