如何在Posix系统中获得总可用磁盘空间?

时间:2010-10-10 10:18:49

标签: c++ linux macos unix posix

我正在编写一个跨平台的应用程序,我需要总的可用磁盘空间。对于posix系统(Linux和Macos),我使用的是statvfs。我创建了这个C ++方法:

long OSSpecificPosix::getFreeDiskSpace(const char* absoluteFilePath) {
   struct statvfs buf;

   if (!statvfs(absoluteFilePath, &buf)) {
      unsigned long blksize, blocks, freeblks, disk_size, used, free;
      blksize = buf.f_bsize;
      blocks = buf.f_blocks;
      freeblks = buf.f_bfree;

      disk_size = blocks*blksize;
      free = freeblks*blksize;
      used = disk_size - free;

      return free;
   }
   else {
      return -1;
   }
}

不幸的是,我得到了一些我无法理解的奇怪价值观。例如: f_blocks = 73242188 f_bsize = 1048576 f_bfree = 50393643 ...

这些值是以位,字节还是其他形式存在的?我在这里读取stackoverflow那些应该是字节,但后来我得到的总字节数是免费的: f_bsize * f_bfree = 1048576 * 50393643 但这意味着49212.542GB ......太多......

我是否对代码或其他任何内容做错了? 谢谢!

4 个答案:

答案 0 :(得分:8)

我不太清楚OSX足以预测这绝对是答案,但f_blocksf_bfree实际上是指“基本块”或“片段”(大小为{{ 1}}字节),而不是“文件系统块大小”(即buf.f_frsize字节):

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html

buf.f_bsize只是提示I / O操作的首选大小,它不一定与文件系统的划分方式有关。

答案 1 :(得分:3)

以下几行:

disk_size = blocks*blksize;
free = freeblks*blksize;

拥有巨型高清时会导致溢出。

我也得到了奇怪的结果,直到我发现我的HD为455GiB,请考虑在进行乘法之前将块,blksize和freeblks变量转换为unsigned long。

这样的事情:

unsigned long long disk_size = (unsigned long long) (blocks) * (unsigned long long) (blksize)

我见过很多像这样的问题,但没有人注意到答案。

答案 2 :(得分:2)

我认为最后两个答案是正确和有用的。但是我通过简单地用函数 statfs 替换函数 statvfs 来解决。然后块大小如预期的那样4096,一切似乎都是正确的。 谢谢!

答案 3 :(得分:1)

uint64_t userAvailableFreeSpace()
{
    struct statvfs stat;
    struct passwd *pw = getpwuid(getuid());
    if ( NULL != pw && 0 == statvfs(pw->pw_dir, &stat) )
    {
        uint64_t freeBytes = (uint64_t)stat.f_bavail * stat.f_frsize;
        return freeBytes;
    }
    return 0ULL;
}